[packages/xfsprogs] - up to 3.2.1
arekm
arekm at pld-linux.org
Tue Jul 15 07:12:01 CEST 2014
commit a7a3a492a383de47624401018ec328f6d31537cd
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Tue Jul 15 07:11:57 2014 +0200
- up to 3.2.1
xfsprogs-git.patch | 27483 ---------------------------------------------------
xfsprogs.spec | 8 +-
2 files changed, 3 insertions(+), 27488 deletions(-)
---
diff --git a/xfsprogs.spec b/xfsprogs.spec
index b217e22..39ea2fc 100644
--- a/xfsprogs.spec
+++ b/xfsprogs.spec
@@ -5,14 +5,13 @@
Summary: Tools for the XFS filesystem
Summary(pl.UTF-8): Narzędzia do systemu plików XFS
Name: xfsprogs
-Version: 3.2.0
-Release: 4
+Version: 3.2.1
+Release: 1
License: LGPL v2.1 (libhandle), GPL v2 (the rest)
Group: Applications/System
Source0: ftp://linux-xfs.sgi.com/projects/xfs/cmd_tars/%{name}-%{version}.tar.gz
-# Source0-md5: 400047b2f6af87c0345b8f0cc00c13db
+# Source0-md5: 5c6905932029c8f9207fe5a0a8aac24b
Source1: xfs_lsprojid
-Patch100: %{name}-git.patch
Patch0: %{name}-miscfix-v2.patch
Patch1: %{name}-pl.po-update.patch
Patch2: %{name}-repair-tcmalloc.patch
@@ -94,7 +93,6 @@ Biblioteki statyczne do XFS.
%prep
%setup -q
-%patch100 -p1
%patch0 -p1
#%patch1 -p1
diff --git a/xfsprogs-git.patch b/xfsprogs-git.patch
deleted file mode 100644
index 4e330d4..0000000
--- a/xfsprogs-git.patch
+++ /dev/null
@@ -1,27483 +0,0 @@
-diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c
-index 71adb57..7ce5ec9 100644
---- a/copy/xfs_copy.c
-+++ b/copy/xfs_copy.c
-@@ -217,25 +217,6 @@ handle_error:
- }
-
- void
--killall(void)
--{
-- int i;
--
-- /* only the parent gets to kill things */
--
-- if (getpid() != parent_pid)
-- return;
--
-- for (i = 0; i < num_targets; i++) {
-- if (target[i].state == ACTIVE) {
-- /* kill up target threads */
-- pthread_kill(target[i].pid, SIGKILL);
-- pthread_mutex_unlock(&targ[i].wait);
-- }
-- }
--}
--
--void
- handler(int sig)
- {
- pid_t pid;
-@@ -400,8 +381,7 @@ read_wbuf(int fd, wbuf *buf, xfs_mount_t *mp)
- if (buf->length > buf->size) {
- do_warn(_("assert error: buf->length = %d, buf->size = %d\n"),
- buf->length, buf->size);
-- killall();
-- abort();
-+ exit(1);
- }
-
- if ((res = read(fd, buf->data, buf->length)) < 0) {
-@@ -594,11 +574,6 @@ main(int argc, char **argv)
-
- parent_pid = getpid();
-
-- if (atexit(killall)) {
-- do_log(_("%s: couldn't register atexit function.\n"), progname);
-- die_perror();
-- }
--
- /* open up source -- is it a file? */
-
- open_flags = O_RDONLY;
-@@ -725,7 +700,7 @@ main(int argc, char **argv)
- if (source_blocksize > source_sectorsize) {
- /* get number of leftover sectors in last block of ag header */
-
-- tmp_residue = ((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize)
-+ tmp_residue = ((XFS_AGFL_DADDR(mp) + 1) * BBSIZE)
- % source_blocksize;
- first_residue = (tmp_residue == 0) ? 0 :
- source_blocksize - tmp_residue;
-@@ -738,10 +713,10 @@ main(int argc, char **argv)
- exit(1);
- }
-
-- first_agbno = (((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize)
-+ first_agbno = (((XFS_AGFL_DADDR(mp) + 1) * BBSIZE)
- + first_residue) / source_blocksize;
- ASSERT(first_agbno != 0);
-- ASSERT( ((((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize)
-+ ASSERT(((((XFS_AGFL_DADDR(mp) + 1) * BBSIZE)
- + first_residue) % source_blocksize) == 0);
-
- /* now open targets */
-@@ -1177,9 +1152,6 @@ main(int argc, char **argv)
- }
-
- check_errors();
-- killall();
-- pthread_exit(NULL);
-- /*NOTREACHED*/
- return 0;
- }
-
-diff --git a/db/Makefile b/db/Makefile
-index 9485b82..bae6154 100644
---- a/db/Makefile
-+++ b/db/Makefile
-@@ -14,7 +14,7 @@ HFILES = addr.h agf.h agfl.h agi.h attr.h attrshort.h bit.h block.h bmap.h \
- io.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
- CFILES = $(HFILES:.h=.c)
--LSRCFILES = xfs_admin.sh xfs_check.sh xfs_ncheck.sh xfs_metadump.sh
-+LSRCFILES = xfs_admin.sh xfs_ncheck.sh xfs_metadump.sh
-
- LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD)
- LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG)
-@@ -38,7 +38,6 @@ 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_check.sh $(PKG_SBIN_DIR)/xfs_check
- $(INSTALL) -m 755 xfs_ncheck.sh $(PKG_SBIN_DIR)/xfs_ncheck
- $(INSTALL) -m 755 xfs_metadump.sh $(PKG_SBIN_DIR)/xfs_metadump
- install-dev:
-diff --git a/db/agi.c b/db/agi.c
-index 398bdbb..6f167ac 100644
---- a/db/agi.c
-+++ b/db/agi.c
-@@ -57,6 +57,8 @@ const field_t agi_flds[] = {
- { "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 }
- };
-
-diff --git a/db/attrset.c b/db/attrset.c
-index 762b3bf..ea5261a 100644
---- a/db/attrset.c
-+++ b/db/attrset.c
-@@ -170,7 +170,7 @@ attr_set_f(
- out:
- mp->m_flags &= ~LIBXFS_MOUNT_COMPAT_ATTR;
- if (ip)
-- libxfs_iput(ip, 0);
-+ IRELE(ip);
- if (value)
- free(value);
- return 0;
-@@ -244,6 +244,6 @@ attr_remove_f(
- out:
- mp->m_flags &= ~LIBXFS_MOUNT_COMPAT_ATTR;
- if (ip)
-- libxfs_iput(ip, 0);
-+ IRELE(ip);
- return 0;
- }
-diff --git a/db/btblock.c b/db/btblock.c
-index 1ea0cff..cdb8b1d 100644
---- a/db/btblock.c
-+++ b/db/btblock.c
-@@ -60,6 +60,12 @@ struct xfs_db_btree {
- 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),
-@@ -84,6 +90,12 @@ struct xfs_db_btree {
- 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),
-+ },
- { 0,
- },
- };
-diff --git a/db/metadump.c b/db/metadump.c
-index 09bb85a..38cd441 100644
---- a/db/metadump.c
-+++ b/db/metadump.c
-@@ -1917,6 +1917,7 @@ scanfunc_ino(
- xfs_inobt_ptr_t *pp;
- int i;
- int numrecs;
-+ int finobt = *(int *) arg;
-
- numrecs = be16_to_cpu(block->bb_numrecs);
-
-@@ -1928,6 +1929,14 @@ scanfunc_ino(
- 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))
-@@ -1967,6 +1976,7 @@ copy_inodes(
- {
- xfs_agblock_t root;
- int levels;
-+ int finobt = 0;
-
- root = be32_to_cpu(agi->agi_root);
- levels = be32_to_cpu(agi->agi_level);
-@@ -1985,7 +1995,20 @@ copy_inodes(
- return 1;
- }
-
-- return scan_btree(agno, root, levels, TYP_INOBT, agi, scanfunc_ino);
-+ 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
-diff --git a/db/write.c b/db/write.c
-index ca8bd0f..0157a44 100644
---- a/db/write.c
-+++ b/db/write.c
-@@ -565,7 +565,7 @@ convert_arg(
- return NULL;
-
- /* Does the value fit into the range of the destination bitfield? */
-- if ((val >> bit_length) > 0)
-+ if (bit_length < 64 && (val >> bit_length) > 0)
- return NULL;
- /*
- * If the length of the field is not a multiple of a byte, push
-diff --git a/db/xfs_check.sh b/db/xfs_check.sh
-deleted file mode 100755
-index 553da63..0000000
---- a/db/xfs_check.sh
-+++ /dev/null
-@@ -1,42 +0,0 @@
--#!/bin/sh -f
--#
--# Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
--#
--
--OPTS=" "
--DBOPTS=" "
--USAGE="Usage: xfs_check [-fsvV] [-l logdev] [-i ino]... [-b bno]... special"
--
--echo "xfs_check is deprecated and scheduled for removal in June 2014."
--echo "Please use xfs_repair -n <dev> instead."
--
--while getopts "b:fi:l:stvV" c
--do
-- case $c in
-- s) OPTS=$OPTS"-s ";;
-- t) OPTS=$OPTS"-t ";;
-- v) OPTS=$OPTS"-v ";;
-- i) OPTS=$OPTS"-i "$OPTARG" ";;
-- b) OPTS=$OPTS"-b "$OPTARG" ";;
-- f) DBOPTS=$DBOPTS" -f";;
-- l) DBOPTS=$DBOPTS" -l "$OPTARG" ";;
-- V) xfs_db -p xfs_check -V
-- status=$?
-- exit $status
-- ;;
-- \?) echo $USAGE 1>&2
-- exit 2
-- ;;
-- esac
--done
--set -- extra $@
--shift $OPTIND
--case $# in
-- 1) xfs_db$DBOPTS -F -i -p xfs_check -c "check$OPTS" $1
-- status=$?
-- ;;
-- *) echo $USAGE 1>&2
-- exit 2
-- ;;
--esac
--exit $status
-diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
-index 3818f02..48629fd 100644
---- a/fsr/xfs_fsr.c
-+++ b/fsr/xfs_fsr.c
-@@ -554,6 +554,8 @@ fsrallfs(char *mtab, int howlong, char *leftofffile)
- 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)
-@@ -1203,14 +1205,20 @@ out:
- * 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 routinte.
-+ * 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;
-+ 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;
-@@ -1218,7 +1226,7 @@ packfile(char *fname, char *tname, int fd,
- static xfs_swapext_t sx;
- struct xfs_flock64 space;
- off64_t cnt, pos;
-- void *fbuf;
-+ void *fbuf = NULL;
- int ct, wc, wc_b4;
- char ffname[SMBUFSZ];
- int ffd = -1;
-@@ -1234,7 +1242,8 @@ packfile(char *fname, char *tname, int fd,
- if (cur_nextents == 1 || cur_nextents <= nextents) {
- if (vflag)
- fsrprintf(_("%s already fully defragmented.\n"), fname);
-- return 1; /* indicates no change/no error */
-+ retval = 1; /* indicates no change/no error */
-+ goto out;
- }
-
- if (dflag)
-@@ -1246,15 +1255,14 @@ packfile(char *fname, char *tname, int fd,
- if (vflag)
- fsrprintf(_("could not open tmp file: %s: %s\n"),
- tname, strerror(errno));
-- return -1;
-+ 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);
-- close(tfd);
-- return -1;
-+ goto out;
- }
-
- /* Setup extended inode flags, project identifier, etc */
-@@ -1262,15 +1270,13 @@ packfile(char *fname, char *tname, int fd,
- if (ioctl(tfd, XFS_IOC_FSSETXATTR, fsxp) < 0) {
- fsrprintf(_("could not set inode attrs on tmp: %s\n"),
- tname);
-- close(tfd);
-- return -1;
-+ goto out;
- }
- }
-
- if ((ioctl(tfd, XFS_IOC_DIOINFO, &dio)) < 0 ) {
- fsrprintf(_("could not get DirectIO info on tmp: %s\n"), tname);
-- close(tfd);
-- return -1;
-+ goto out;
- }
-
- dio_min = dio.d_miniosz;
-@@ -1292,8 +1298,7 @@ packfile(char *fname, char *tname, int fd,
-
- if (!(fbuf = (char *)memalign(dio.d_mem, blksz_dio))) {
- fsrprintf(_("could not allocate buf: %s\n"), tname);
-- close(tfd);
-- return -1;
-+ goto out;
- }
-
- if (nfrags) {
-@@ -1304,9 +1309,7 @@ packfile(char *fname, char *tname, int fd,
- if ((ffd = open(ffname, openopts, 0666)) < 0) {
- fsrprintf(_("could not open fragfile: %s : %s\n"),
- ffname, strerror(errno));
-- close(tfd);
-- free(fbuf);
-- return -1;
-+ goto out;
- }
- unlink(ffname);
- }
-@@ -1322,7 +1325,11 @@ packfile(char *fname, char *tname, int fd,
- fsrprintf(_("could not trunc tmp %s\n"),
- tname);
- }
-- lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR);
-+ if (lseek64(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 */
-@@ -1336,21 +1343,19 @@ packfile(char *fname, char *tname, int fd,
- if (ioctl(tfd, XFS_IOC_RESVSP64, &space) < 0) {
- fsrprintf(_("could not pre-allocate tmp space:"
- " %s\n"), tname);
-- close(tfd);
-- free(fbuf);
-- return -1;
-+ goto out;
-+ }
-+ if (lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
-+ fsrprintf(_("could not lseek in tmpfile: %s : %s\n"),
-+ tname, strerror(errno));
-+ goto out;
- }
-- lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR);
- }
- } /* end of space allocation loop */
-
- if (lseek64(tfd, 0, SEEK_SET)) {
- fsrprintf(_("Couldn't rewind on temporary file\n"));
-- close(tfd);
-- if (ffd != -1)
-- close(ffd);
-- free(fbuf);
-- return -1;
-+ goto out;
- }
-
- /* Check if the temporary file has fewer extents */
-@@ -1360,19 +1365,24 @@ packfile(char *fname, char *tname, int fd,
- if (cur_nextents <= new_nextents) {
- if (vflag)
- fsrprintf(_("No improvement will be made (skipping): %s\n"), fname);
-- free(fbuf);
-- close(tfd);
-- if (ffd != -1)
-- close(ffd);
-- return 1; /* no change/no error */
-+ 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) {
-- lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR);
-- lseek64(fd, outmap[extent].bmv_length, SEEK_CUR);
-+ if (lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR) < 0) {
-+ fsrprintf(_("could not lseek in tmpfile: %s : %s\n"),
-+ tname, strerror(errno));
-+ goto out;
-+ }
-+ if (lseek64(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 */
-@@ -1435,11 +1445,7 @@ packfile(char *fname, char *tname, int fd,
- tname);
- }
- }
-- free(fbuf);
-- close(tfd);
-- if (ffd != -1)
-- close(ffd);
-- return -1;
-+ goto out;
- }
- if (nfrags) {
- /* Do a matching write to the tmp file */
-@@ -1452,12 +1458,16 @@ packfile(char *fname, char *tname, int fd,
- }
- }
- }
-- ftruncate64(tfd, statp->bs_size);
-- if (ffd != -1)
-- close(ffd);
-- fsync(tfd);
--
-- free(fbuf);
-+ if (ftruncate64(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;
-@@ -1471,8 +1481,7 @@ packfile(char *fname, char *tname, int fd,
- if (vflag)
- fsrprintf(_("failed to fchown tmpfile %s: %s\n"),
- tname, strerror(errno));
-- close(tfd);
-- return -1;
-+ goto out;
- }
-
- /* Swap the extents */
-@@ -1494,8 +1503,7 @@ packfile(char *fname, char *tname, int fd,
- fsrprintf(_("XFS_IOC_SWAPEXT failed: %s: %s\n"),
- fname, strerror(errno));
- }
-- close(tfd);
-- return -1;
-+ goto out;
- }
-
- /* Report progress */
-@@ -1504,8 +1512,15 @@ packfile(char *fname, char *tname, int fd,
- cur_nextents, new_nextents,
- (new_nextents <= nextents ? "DONE" : " " ),
- fname);
-- close(tfd);
-- return 0;
-+ retval = 0;
-+
-+out:
-+ free(fbuf);
-+ if (tfd != -1)
-+ close(tfd);
-+ if (ffd != -1)
-+ close(ffd);
-+ return retval;
- }
-
- char *
-diff --git a/growfs/xfs_growfs.c b/growfs/xfs_growfs.c
-index 77da707..8e611b6 100644
---- a/growfs/xfs_growfs.c
-+++ b/growfs/xfs_growfs.c
-@@ -56,12 +56,13 @@ report_info(
- int projid32bit,
- int crcs_enabled,
- int cimode,
-- int ftype_enabled)
-+ int ftype_enabled,
-+ int finobt_enabled)
- {
- printf(_(
- "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n"
- " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
-- " =%-22s crc=%u\n"
-+ " =%-22s crc=%-8u finobt=%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"
-@@ -71,7 +72,7 @@ report_info(
-
- mntpoint, geo.inodesize, geo.agcount, geo.agblocks,
- "", geo.sectsize, attrversion, projid32bit,
-- "", crcs_enabled,
-+ "", crcs_enabled, finobt_enabled,
- "", geo.blocksize, (unsigned long long)geo.datablocks,
- geo.imaxpct,
- "", geo.sunit, geo.swidth,
-@@ -123,6 +124,7 @@ main(int argc, char **argv)
- int projid32bit;
- int crcs_enabled;
- int ftype_enabled = 0;
-+ int finobt_enabled; /* free inode btree */
-
- progname = basename(argv[0]);
- setlocale(LC_ALL, "");
-@@ -244,11 +246,12 @@ main(int argc, char **argv)
- 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;
- if (nflag) {
- report_info(geo, datadev, isint, logdev, rtdev,
- lazycount, dirversion, logversion,
- attrversion, projid32bit, crcs_enabled, ci,
-- ftype_enabled);
-+ ftype_enabled, finobt_enabled);
- exit(0);
- }
-
-@@ -285,7 +288,8 @@ main(int argc, char **argv)
-
- report_info(geo, datadev, isint, logdev, rtdev,
- lazycount, dirversion, logversion,
-- attrversion, projid32bit, crcs_enabled, ci, ftype_enabled);
-+ attrversion, projid32bit, crcs_enabled, ci, ftype_enabled,
-+ finobt_enabled);
-
- ddsize = xi.dsize;
- dlsize = ( xi.logBBsize? xi.logBBsize :
-diff --git a/include/libxfs.h b/include/libxfs.h
-index 9c10957..45a924f 100644
---- a/include/libxfs.h
-+++ b/include/libxfs.h
-@@ -480,7 +480,6 @@ typedef struct xfs_inode_log_item {
- 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 */
-- int ili_lock_flags;
- } xfs_inode_log_item_t;
-
- typedef struct xfs_buf_log_item {
-@@ -535,9 +534,7 @@ extern xfs_buf_t *libxfs_trans_getsb (xfs_trans_t *, xfs_mount_t *, int);
-
- extern int libxfs_trans_iget (xfs_mount_t *, xfs_trans_t *, xfs_ino_t,
- uint, uint, struct xfs_inode **);
--extern void libxfs_trans_iput(xfs_trans_t *, struct xfs_inode *, uint);
- extern void libxfs_trans_ijoin (xfs_trans_t *, struct xfs_inode *, uint);
--extern void libxfs_trans_ihold (xfs_trans_t *, struct xfs_inode *);
- extern void libxfs_trans_ijoin_ref(xfs_trans_t *, struct xfs_inode *, int);
- extern void libxfs_trans_log_inode (xfs_trans_t *, struct xfs_inode *,
- uint);
-@@ -656,7 +653,9 @@ extern int libxfs_iflush_int (xfs_inode_t *, xfs_buf_t *);
- /* Inode Cache Interfaces */
- extern int libxfs_iget (xfs_mount_t *, xfs_trans_t *, xfs_ino_t,
- uint, xfs_inode_t **, xfs_daddr_t);
--extern void libxfs_iput (xfs_inode_t *, uint);
-+extern void libxfs_iput (xfs_inode_t *);
-+
-+#define IRELE(ip) libxfs_iput(ip)
-
- /* Shared utility routines */
- extern unsigned int libxfs_log2_roundup(unsigned int i);
-@@ -760,6 +759,7 @@ bool xfs_dinode_verify(struct xfs_mount *mp, xfs_ino_t ino,
- /* xfs_sb.h */
- #define libxfs_mod_sb xfs_mod_sb
- #define libxfs_sb_from_disk xfs_sb_from_disk
-+#define libxfs_sb_quota_from_disk xfs_sb_quota_from_disk
- #define libxfs_sb_to_disk xfs_sb_to_disk
-
- /* xfs_symlink.h */
-diff --git a/include/xfs_ag.h b/include/xfs_ag.h
-index 0fdd410..2531658 100644
---- a/include/xfs_ag.h
-+++ b/include/xfs_ag.h
-@@ -166,24 +166,30 @@ typedef struct xfs_agi {
- __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 0x00000001
--#define XFS_AGI_VERSIONNUM 0x00000002
--#define XFS_AGI_SEQNO 0x00000004
--#define XFS_AGI_LENGTH 0x00000008
--#define XFS_AGI_COUNT 0x00000010
--#define XFS_AGI_ROOT 0x00000020
--#define XFS_AGI_LEVEL 0x00000040
--#define XFS_AGI_FREECOUNT 0x00000080
--#define XFS_AGI_NEWINO 0x00000100
--#define XFS_AGI_DIRINO 0x00000200
--#define XFS_AGI_UNLINKED 0x00000400
--#define XFS_AGI_NUM_BITS 11
--#define XFS_AGI_ALL_BITS ((1 << XFS_AGI_NUM_BITS) - 1)
-+#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))
-diff --git a/include/xfs_btree.h b/include/xfs_btree.h
-index 6afe0b2..2590d40 100644
---- a/include/xfs_btree.h
-+++ b/include/xfs_btree.h
-@@ -37,6 +37,7 @@ extern kmem_zone_t *xfs_btree_cur_zone;
- #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)
-
- /*
- * For logging record fields.
-@@ -67,6 +68,7 @@ do { \
- case XFS_BTNUM_CNT: __XFS_BTREE_STATS_INC(abtc, stat); break; \
- case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(bmbt, stat); break; \
- case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(ibt, stat); break; \
-+ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(fibt, stat); break; \
- case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \
- } \
- } while (0)
-@@ -80,6 +82,7 @@ do { \
- case XFS_BTNUM_CNT: __XFS_BTREE_STATS_ADD(abtc, stat, val); break; \
- case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_ADD(bmbt, stat, val); break; \
- case XFS_BTNUM_INO: __XFS_BTREE_STATS_ADD(ibt, stat, val); break; \
-+ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_ADD(fibt, stat, val); break; \
- case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \
- } \
- } while (0)
-diff --git a/include/xfs_format.h b/include/xfs_format.h
-index 77f6b8b..758052f 100644
---- a/include/xfs_format.h
-+++ b/include/xfs_format.h
-@@ -202,6 +202,8 @@ typedef __be32 xfs_alloc_ptr_t;
- */
- #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))
-@@ -244,7 +246,17 @@ 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_PREALLOC_BLOCKS(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1))
-+#define XFS_FIBT_BLOCK(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1))
-+
-+/*
-+ * The first data block of an AG depends on whether the filesystem was formatted
-+ * with the finobt feature. If so, account for the finobt reserved root btree
-+ * block.
-+ */
-+#define XFS_PREALLOC_BLOCKS(mp) \
-+ (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \
-+ XFS_FIBT_BLOCK(mp) + 1 : \
-+ XFS_IBT_BLOCK(mp) + 1)
-
-
-
-diff --git a/include/xfs_fs.h b/include/xfs_fs.h
-index 554fd66..59c40fc 100644
---- a/include/xfs_fs.h
-+++ b/include/xfs_fs.h
-@@ -238,6 +238,7 @@ typedef struct xfs_fsop_resblks {
- #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 */
-
-
- /*
-diff --git a/include/xfs_ialloc.h b/include/xfs_ialloc.h
-index a8f76a5..c8ac0a4 100644
---- a/include/xfs_ialloc.h
-+++ b/include/xfs_ialloc.h
-@@ -89,7 +89,7 @@ xfs_difree(
- struct xfs_trans *tp, /* transaction pointer */
- xfs_ino_t inode, /* inode to be freed */
- struct xfs_bmap_free *flist, /* extents to free */
-- int *delete, /* set if inode cluster was deleted */
-+ int *deleted, /* set if inode cluster was deleted */
- xfs_ino_t *first_ino); /* first inode in deleted cluster */
-
- /*
-diff --git a/include/xfs_ialloc_btree.h b/include/xfs_ialloc_btree.h
-index f38b220..d7ebea7 100644
---- a/include/xfs_ialloc_btree.h
-+++ b/include/xfs_ialloc_btree.h
-@@ -58,7 +58,8 @@ struct xfs_mount;
- ((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);
-+ struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t,
-+ xfs_btnum_t);
- extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int);
-
- #endif /* __XFS_IALLOC_BTREE_H__ */
-diff --git a/include/xfs_sb.h b/include/xfs_sb.h
-index f7b2fe7..950d1ea 100644
---- a/include/xfs_sb.h
-+++ b/include/xfs_sb.h
-@@ -587,7 +587,9 @@ xfs_sb_has_compat_feature(
- return (sbp->sb_features_compat & feature) != 0;
- }
-
--#define XFS_SB_FEAT_RO_COMPAT_ALL 0
-+#define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */
-+#define XFS_SB_FEAT_RO_COMPAT_ALL \
-+ (XFS_SB_FEAT_RO_COMPAT_FINOBT)
- #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL
- static inline bool
- xfs_sb_has_ro_compat_feature(
-@@ -641,6 +643,12 @@ static inline int xfs_sb_version_hasftype(struct xfs_sb *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);
-+}
-+
- /*
- * end of superblock version macros
- */
-diff --git a/include/xfs_trans_space.h b/include/xfs_trans_space.h
-index 7d2c920..a7d1721 100644
---- a/include/xfs_trans_space.h
-+++ b/include/xfs_trans_space.h
-@@ -47,7 +47,9 @@
- #define XFS_DIRREMOVE_SPACE_RES(mp) \
- XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK)
- #define XFS_IALLOC_SPACE_RES(mp) \
-- (XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels - 1)
-+ (XFS_IALLOC_BLOCKS(mp) + \
-+ (xfs_sb_version_hasfinobt(&mp->m_sb) ? 2 : 1 * \
-+ ((mp)->m_in_maxlevels - 1)))
-
- /*
- * Space reservation values for various transactions.
-@@ -82,5 +84,8 @@
- (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__ */
-diff --git a/include/xfs_types.h b/include/xfs_types.h
-index 82bbc34..65c6e66 100644
---- a/include/xfs_types.h
-+++ b/include/xfs_types.h
-@@ -134,7 +134,7 @@ typedef enum {
-
- typedef enum {
- XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi,
-- XFS_BTNUM_MAX
-+ XFS_BTNUM_FINOi, XFS_BTNUM_MAX
- } xfs_btnum_t;
-
- struct xfs_name {
-diff --git a/libxfs/init.c b/libxfs/init.c
-index 0924948..06458e5 100644
---- a/libxfs/init.c
-+++ b/libxfs/init.c
-@@ -778,9 +778,9 @@ void
- libxfs_rtmount_destroy(xfs_mount_t *mp)
- {
- if (mp->m_rsumip)
-- libxfs_iput(mp->m_rsumip, 0);
-+ IRELE(mp->m_rsumip);
- if (mp->m_rbmip)
-- libxfs_iput(mp->m_rbmip, 0);
-+ IRELE(mp->m_rbmip);
- mp->m_rsumip = mp->m_rbmip = NULL;
- }
-
-diff --git a/libxfs/linux.c b/libxfs/linux.c
-index 2e07d54..8d1a117 100644
---- a/libxfs/linux.c
-+++ b/libxfs/linux.c
-@@ -141,10 +141,20 @@ platform_findsizes(char *path, int fd, long long *sz, int *bsz)
- exit(1);
- }
- if ((st.st_mode & S_IFMT) == S_IFREG) {
-+ struct xfs_fsop_geom_v1 geom = { 0 };
-+
- *sz = (long long)(st.st_size >> 9);
-- *bsz = BBSIZE;
-- if (BBSIZE > max_block_alignment)
-- max_block_alignment = BBSIZE;
-+ if (ioctl(fd, XFS_IOC_FSGEOMETRY_V1, &geom) < 0) {
-+ /*
-+ * fall back to BBSIZE; mkfs might fail if there's a
-+ * size mismatch between the image & the host fs...
-+ */
-+ *bsz = BBSIZE;
-+ } else
-+ *bsz = geom.sectsize;
-+
-+ if (*bsz > max_block_alignment)
-+ max_block_alignment = *bsz;
- return;
- }
-
-diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
-index 57c12c1..0294c98 100644
---- a/libxfs/rdwr.c
-+++ b/libxfs/rdwr.c
-@@ -19,6 +19,37 @@
- #include <xfs/libxfs.h>
- #include "init.h"
-
-+/*
-+ * 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
-@@ -632,6 +663,12 @@ libxfs_putbuf(xfs_buf_t *bp)
- pthread_mutex_unlock(&bp->b_lock);
- }
- }
-+ /*
-+ * ensure that any errors on this use of the buffer don't carry
-+ * over to the next user.
-+ */
-+ bp->b_error = 0;
-+
- cache_node_put(libxfs_bcache, (struct cache_node *)bp);
- }
-
-@@ -907,10 +944,10 @@ libxfs_writebufr(xfs_buf_t *bp)
- }
-
- #ifdef IO_DEBUG
-- printf("%lx: %s: wrote %u bytes, blkno=%llu(%llu), %p\n",
-+ 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);
-+ (long long)bp->b_bn, bp, error);
- #endif
- if (!error) {
- bp->b_flags |= LIBXFS_B_UPTODATE;
-@@ -928,6 +965,7 @@ libxfs_writebuf_int(xfs_buf_t *bp, int flags)
- * 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;
- }
-@@ -946,6 +984,7 @@ libxfs_writebuf(xfs_buf_t *bp, int flags)
- * 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;
-@@ -1103,7 +1142,7 @@ libxfs_idestroy(xfs_inode_t *ip)
- }
-
- void
--libxfs_iput(xfs_inode_t *ip, uint lock_flags)
-+libxfs_iput(xfs_inode_t *ip)
- {
- if (ip->i_itemp)
- kmem_zone_free(xfs_ili_zone, ip->i_itemp);
-diff --git a/libxfs/trans.c b/libxfs/trans.c
-index c443863..13d21b2 100644
---- a/libxfs/trans.c
-+++ b/libxfs/trans.c
-@@ -110,7 +110,7 @@ libxfs_trans_roll(
- /*
- * Commit the current transaction.
- * If this commit failed, then it'd just unlock those items that
-- * are not marked ihold. That also means that a filesystem shutdown
-+ * 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.
- */
-@@ -248,27 +248,6 @@ libxfs_trans_iget(
- }
-
- void
--libxfs_trans_iput(
-- xfs_trans_t *tp,
-- xfs_inode_t *ip,
-- uint lock_flags)
--{
-- xfs_inode_log_item_t *iip;
--
-- if (tp == NULL) {
-- libxfs_iput(ip, lock_flags);
-- return;
-- }
--
-- ASSERT(ip->i_transp == tp);
-- iip = ip->i_itemp;
-- ASSERT(iip != NULL);
-- xfs_trans_del_item(&iip->ili_item);
--
-- libxfs_iput(ip, lock_flags);
--}
--
--void
- libxfs_trans_ijoin(
- xfs_trans_t *tp,
- xfs_inode_t *ip,
-@@ -301,7 +280,6 @@ libxfs_trans_ijoin_ref(
- ASSERT(ip->i_itemp != NULL);
-
- xfs_trans_ijoin(tp, ip, lock_flags);
-- ip->i_itemp->ili_lock_flags = lock_flags;
-
- #ifdef XACT_DEBUG
- fprintf(stderr, "ijoin_ref'd inode %llu, transaction %p\n", ip->i_ino, tp);
-@@ -309,21 +287,6 @@ libxfs_trans_ijoin_ref(
- }
-
- void
--libxfs_trans_ihold(
-- xfs_trans_t *tp,
-- xfs_inode_t *ip)
--{
-- ASSERT(ip->i_transp == tp);
-- ASSERT(ip->i_itemp != NULL);
--
-- ip->i_itemp->ili_lock_flags = 1;
--
--#ifdef XACT_DEBUG
-- fprintf(stderr, "ihold'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)
-@@ -702,7 +665,7 @@ inode_item_done(
- if (!(iip->ili_fields & XFS_ILOG_ALL)) {
- ip->i_transp = NULL; /* disassociate from transaction */
- iip->ili_flags = 0; /* reset all flags */
-- goto ili_done;
-+ return;
- }
-
- /*
-@@ -712,7 +675,7 @@ inode_item_done(
- if (error) {
- fprintf(stderr, _("%s: warning - imap_to_bp failed (%d)\n"),
- progname, error);
-- goto ili_done;
-+ return;
- }
-
- XFS_BUF_SET_FSPRIVATE(bp, iip);
-@@ -720,7 +683,7 @@ inode_item_done(
- if (error) {
- fprintf(stderr, _("%s: warning - iflush_int failed (%d)\n"),
- progname, error);
-- goto ili_done;
-+ return;
- }
-
- ip->i_transp = NULL; /* disassociate from transaction */
-@@ -728,16 +691,9 @@ inode_item_done(
- XFS_BUF_SET_FSPRIVATE2(bp, NULL); /* remove xact ptr */
- libxfs_writebuf(bp, 0);
- #ifdef XACT_DEBUG
-- fprintf(stderr, "flushing dirty inode %llu, buffer %p (hold=%u)\n",
-- ip->i_ino, bp, iip->ili_lock_flags);
-+ fprintf(stderr, "flushing dirty inode %llu, buffer %p\n",
-+ ip->i_ino, bp);
- #endif
--ili_done:
-- if (iip->ili_lock_flags) {
-- iip->ili_lock_flags = 0;
-- return;
-- }
-- /* free the inode */
-- libxfs_iput(ip, 0);
- }
-
- static void
-@@ -818,10 +774,6 @@ inode_item_unlock(
- ip->i_transp = NULL;
-
- iip->ili_flags = 0;
-- if (!iip->ili_lock_flags)
-- libxfs_iput(ip, 0);
-- else
-- iip->ili_lock_flags = 0;
- }
-
- /*
-diff --git a/libxfs/util.c b/libxfs/util.c
-index 4c40324..9504e33 100644
---- a/libxfs/util.c
-+++ b/libxfs/util.c
-@@ -595,7 +595,6 @@ libxfs_alloc_file_space(
- break;
- }
- xfs_trans_ijoin(tp, ip, 0);
-- xfs_trans_ihold(tp, ip);
-
- xfs_bmap_init(&free_list, &firstfsb);
- error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb,
-diff --git a/libxfs/xfs.h b/libxfs/xfs.h
-index 5a21590..30a316d 100644
---- a/libxfs/xfs.h
-+++ b/libxfs/xfs.h
-@@ -292,7 +292,6 @@ roundup_64(__uint64_t x, __uint32_t y)
- #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_ihold libxfs_trans_ihold
- #define xfs_trans_ijoin libxfs_trans_ijoin
- #define xfs_trans_ijoin_ref libxfs_trans_ijoin_ref
- #define xfs_trans_init libxfs_trans_init
-diff --git a/libxfs/xfs_attr_remote.c b/libxfs/xfs_attr_remote.c
-index 5cf5c73..08b983b 100644
---- a/libxfs/xfs_attr_remote.c
-+++ b/libxfs/xfs_attr_remote.c
-@@ -85,7 +85,7 @@ xfs_attr3_rmt_verify(
- 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) >= XATTR_SIZE_MAX)
-+ be32_to_cpu(rmt->rm_bytes) > XATTR_SIZE_MAX)
- return false;
- if (rmt->rm_owner == 0)
- return false;
-diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c
-index 9be4abd..cc823f5 100644
---- a/libxfs/xfs_btree.c
-+++ b/libxfs/xfs_btree.c
-@@ -27,9 +27,10 @@ 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, XFS_BMAP_MAGIC, XFS_IBT_MAGIC },
-+ { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC,
-+ XFS_FIBT_MAGIC },
- { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC,
-- XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC }
-+ XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC }
- };
- #define xfs_btree_magic(cur) \
- xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum]
-@@ -1099,6 +1100,7 @@ xfs_btree_set_refs(
- 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:
-diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c
-index b70454e..b731b54 100644
---- a/libxfs/xfs_da_btree.c
-+++ b/libxfs/xfs_da_btree.c
-@@ -2582,7 +2582,8 @@ xfs_da_get_buf(
- mapp, nmap, 0);
- error = bp ? bp->b_error : XFS_ERROR(EIO);
- if (error) {
-- xfs_trans_brelse(trans, bp);
-+ if (bp)
-+ xfs_trans_brelse(trans, bp);
- goto out_free;
- }
-
-diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c
-index c19d84a..5462c54 100644
---- a/libxfs/xfs_ialloc.c
-+++ b/libxfs/xfs_ialloc.c
-@@ -88,6 +88,66 @@ xfs_inobt_get_rec(
- }
-
- /*
-+ * Insert a single inobt record. Cursor must already point to desired location.
-+ */
-+STATIC int
-+xfs_inobt_insert_rec(
-+ struct xfs_btree_cur *cur,
-+ __int32_t freecount,
-+ xfs_inofree_t free,
-+ int *stat)
-+{
-+ 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_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
-@@ -286,13 +346,10 @@ xfs_ialloc_ag_alloc(
- {
- xfs_agi_t *agi; /* allocation group header */
- xfs_alloc_arg_t args; /* allocation argument structure */
-- xfs_btree_cur_t *cur; /* inode btree cursor */
- xfs_agnumber_t agno;
- int error;
-- int i;
- xfs_agino_t newino; /* new first inode's number */
- xfs_agino_t newlen; /* new number of inodes */
-- xfs_agino_t thisino; /* current inode number, for loop */
- int isaligned = 0; /* inode allocation at stripe unit */
- /* boundary */
- struct xfs_perag *pag;
-@@ -430,29 +487,19 @@ xfs_ialloc_ag_alloc(
- agi->agi_newino = cpu_to_be32(newino);
-
- /*
-- * Insert records describing the new inode chunk into the btree.
-+ * Insert records describing the new inode chunk into the btrees.
- */
-- cur = xfs_inobt_init_cursor(args.mp, tp, agbp, agno);
-- for (thisino = newino;
-- thisino < newino + newlen;
-- thisino += XFS_INODES_PER_CHUNK) {
-- cur->bc_rec.i.ir_startino = thisino;
-- cur->bc_rec.i.ir_freecount = XFS_INODES_PER_CHUNK;
-- cur->bc_rec.i.ir_free = XFS_INOBT_ALL_FREE;
-- error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, &i);
-- if (error) {
-- xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
-- return error;
-- }
-- ASSERT(i == 0);
-- error = xfs_btree_insert(cur, &i);
-- if (error) {
-- xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
-+ 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;
-- }
-- ASSERT(i == 1);
- }
-- xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
- /*
- * Log allocation group header fields
- */
-@@ -652,7 +699,7 @@ xfs_ialloc_get_rec(
- * available.
- */
- STATIC int
--xfs_dialloc_ag(
-+xfs_dialloc_ag_slow(
- struct xfs_trans *tp,
- struct xfs_buf *agbp,
- xfs_ino_t parent,
-@@ -678,7 +725,7 @@ xfs_dialloc_ag(
- ASSERT(pag->pagi_freecount > 0);
-
- restart_pagno:
-- cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
-+ 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.
-@@ -910,6 +957,215 @@ error0:
- return error;
- }
-
-+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;
-+ struct xfs_btree_cur *tcur;
-+ struct xfs_inobt_rec_incore rec;
-+ struct xfs_inobt_rec_incore trec;
-+ xfs_ino_t ino;
-+ int error;
-+ int offset;
-+ int i, j;
-+
-+ if (!xfs_sb_version_hasfinobt(&mp->m_sb))
-+ return xfs_dialloc_ag_slow(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;
-+
-+ if (agno == pagno) {
-+ /*
-+ * We're in the same AG as the parent inode so allocate the
-+ * closest inode to the parent.
-+ */
-+ error = xfs_inobt_lookup(cur, pagino, XFS_LOOKUP_LE, &i);
-+ if (error)
-+ goto error_cur;
-+ if (i == 1) {
-+ error = xfs_inobt_get_rec(cur, &rec, &i);
-+ if (error)
-+ goto error_cur;
-+ XFS_WANT_CORRUPTED_GOTO(i == 1, error_cur);
-+
-+ /*
-+ * 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))
-+ goto alloc_inode;
-+ }
-+
-+ error = xfs_btree_dup_cursor(cur, &tcur);
-+ if (error)
-+ goto error_cur;
-+
-+ error = xfs_inobt_lookup(tcur, pagino, XFS_LOOKUP_GE, &j);
-+ if (error)
-+ goto error_tcur;
-+ if (j == 1) {
-+ error = xfs_inobt_get_rec(tcur, &trec, &j);
-+ if (error)
-+ goto error_tcur;
-+ XFS_WANT_CORRUPTED_GOTO(j == 1, error_tcur);
-+ }
-+
-+ if (i == 1 && j == 1) {
-+ if ((pagino - rec.ir_startino + XFS_INODES_PER_CHUNK - 1) >
-+ (trec.ir_startino - pagino)) {
-+ rec = trec;
-+ xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
-+ cur = tcur;
-+ } else {
-+ xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
-+ }
-+ } else if (j == 1) {
-+ rec = trec;
-+ xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
-+ cur = tcur;
-+ } else {
-+ xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
-+ }
-+ } else {
-+ /*
-+ * Different AG from the parent inode. Check the record for the
-+ * most recently allocated inode.
-+ */
-+ if (agi->agi_newino != cpu_to_be32(NULLAGINO)) {
-+ error = xfs_inobt_lookup(cur, agi->agi_newino,
-+ XFS_LOOKUP_EQ, &i);
-+ if (error)
-+ goto error_cur;
-+ if (i == 1) {
-+ error = xfs_inobt_get_rec(cur, &rec, &i);
-+ if (error)
-+ goto error_cur;
-+ XFS_WANT_CORRUPTED_GOTO(i == 1, error_cur);
-+ goto alloc_inode;
-+ }
-+ }
-+
-+ /*
-+ * Allocate the first inode available in the AG.
-+ */
-+ error = xfs_inobt_lookup(cur, 0, XFS_LOOKUP_GE, &i);
-+ if (error)
-+ goto error_cur;
-+ XFS_WANT_CORRUPTED_GOTO(i == 1, error_cur);
-+
-+ error = xfs_inobt_get_rec(cur, &rec, &i);
-+ if (error)
-+ goto error_cur;
-+ XFS_WANT_CORRUPTED_GOTO(i == 1, error_cur);
-+ }
-+
-+alloc_inode:
-+ offset = xfs_lowbit64(rec.ir_free);
-+ 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;
-+
-+ /*
-+ * Lookup and modify the equivalent record in the inobt.
-+ */
-+ tcur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO);
-+
-+ error = xfs_check_agi_freecount(tcur, agi);
-+ if (error)
-+ goto error_tcur;
-+
-+ error = xfs_inobt_lookup(tcur, rec.ir_startino, XFS_LOOKUP_EQ, &i);
-+ if (error)
-+ goto error_tcur;
-+ XFS_WANT_CORRUPTED_GOTO(i == 1, error_tcur);
-+
-+ error = xfs_inobt_get_rec(tcur, &trec, &i);
-+ if (error)
-+ goto error_tcur;
-+ XFS_WANT_CORRUPTED_GOTO(i == 1, error_tcur);
-+ ASSERT((XFS_AGINO_TO_OFFSET(mp, trec.ir_startino) %
-+ XFS_INODES_PER_CHUNK) == 0);
-+
-+ trec.ir_free &= ~XFS_INOBT_MASK(offset);
-+ trec.ir_freecount--;
-+
-+ XFS_WANT_CORRUPTED_GOTO((rec.ir_free == trec.ir_free) &&
-+ (rec.ir_freecount == trec.ir_freecount),
-+ error_tcur);
-+
-+ error = xfs_inobt_update(tcur, &trec);
-+ if (error)
-+ goto error_tcur;
-+
-+ /*
-+ * Update the perag and superblock.
-+ */
-+ 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(tcur, agi);
-+ if (error)
-+ goto error_tcur;
-+ error = xfs_check_agi_freecount(cur, agi);
-+ if (error)
-+ goto error_tcur;
-+
-+ xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
-+ xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
-+ xfs_perag_put(pag);
-+ *inop = ino;
-+ return 0;
-+
-+error_tcur:
-+ xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
-+error_cur:
-+ xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
-+ xfs_perag_put(pag);
-+ return error;
-+}
-+
- /*
- * Allocate an inode on disk.
- *
-@@ -1069,78 +1325,34 @@ out_error:
- return XFS_ERROR(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(
-- xfs_trans_t *tp, /* transaction pointer */
-- xfs_ino_t inode, /* inode to be freed */
-- xfs_bmap_free_t *flist, /* extents to free */
-- int *delete, /* set if inode cluster was deleted */
-- xfs_ino_t *first_ino) /* first inode in deleted cluster */
-+STATIC int
-+xfs_difree_inobt(
-+ struct xfs_mount *mp,
-+ struct xfs_trans *tp,
-+ struct xfs_buf *agbp,
-+ xfs_agino_t agino,
-+ struct xfs_bmap_free *flist,
-+ int *deleted,
-+ xfs_ino_t *first_ino,
-+ struct xfs_inobt_rec_incore *orec)
- {
-- /* REFERENCED */
-- xfs_agblock_t agbno; /* block number containing inode */
-- xfs_buf_t *agbp; /* buffer containing allocation group header */
-- xfs_agino_t agino; /* inode number relative to allocation group */
-- xfs_agnumber_t agno; /* allocation group number */
-- xfs_agi_t *agi; /* allocation group header */
-- xfs_btree_cur_t *cur; /* inode btree cursor */
-- int error; /* error return value */
-- int i; /* result code */
-- int ilen; /* inodes in an inode cluster */
-- xfs_mount_t *mp; /* mount structure for filesystem */
-- int off; /* offset of inode in inode chunk */
-- xfs_inobt_rec_incore_t rec; /* btree record */
-- struct xfs_perag *pag;
-+ 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;
-
-- 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 XFS_ERROR(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 XFS_ERROR(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 XFS_ERROR(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;
-- }
-- agi = XFS_BUF_TO_AGI(agbp);
- ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
-- ASSERT(agbno < be32_to_cpu(agi->agi_length));
-+ 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);
-+ cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO);
-
- error = xfs_check_agi_freecount(cur, agi);
- if (error)
-@@ -1180,7 +1392,7 @@ xfs_difree(
- if (!(mp->m_flags & XFS_MOUNT_IKEEP) &&
- (rec.ir_freecount == XFS_IALLOC_INODES(mp))) {
-
-- *delete = 1;
-+ *deleted = 1;
- *first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino);
-
- /*
-@@ -1208,7 +1420,7 @@ xfs_difree(
- agno, XFS_INO_TO_AGBNO(mp,rec.ir_startino)),
- XFS_IALLOC_BLOCKS(mp), flist, mp);
- } else {
-- *delete = 0;
-+ *deleted = 0;
-
- error = xfs_inobt_update(cur, &rec);
- if (error) {
-@@ -1232,6 +1444,7 @@ xfs_difree(
- if (error)
- goto error0;
-
-+ *orec = rec;
- xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
- return 0;
-
-@@ -1240,6 +1453,189 @@ error0:
- 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(ibtrec->ir_freecount == 1, error);
-+
-+ error = xfs_inobt_insert_rec(cur, ibtrec->ir_freecount,
-+ ibtrec->ir_free, &i);
-+ if (error)
-+ goto error;
-+ ASSERT(i == 1);
-+
-+ goto out;
-+ }
-+
-+ /*
-+ * Read and update the existing record.
-+ */
-+ error = xfs_inobt_get_rec(cur, &rec, &i);
-+ if (error)
-+ goto error;
-+ XFS_WANT_CORRUPTED_GOTO(i == 1, error);
-+
-+ rec.ir_free |= XFS_INOBT_MASK(offset);
-+ rec.ir_freecount++;
-+
-+ XFS_WANT_CORRUPTED_GOTO((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. This is to optimize lookup for inode allocation purposes.
-+ * The following checks determine whether to update the existing record or
-+ * remove it entirely.
-+ */
-+
-+ if (rec.ir_freecount == XFS_IALLOC_INODES(mp) &&
-+ !(mp->m_flags & XFS_MOUNT_IKEEP)) {
-+ /*
-+ * If all inodes are free and we're in !ikeep mode, the entire
-+ * inode chunk has been deallocated. Remove the record from the
-+ * finobt.
-+ */
-+ error = xfs_btree_delete(cur, &i);
-+ if (error)
-+ goto error;
-+ ASSERT(i == 1);
-+ } else {
-+ /*
-+ * The existing finobt record was modified and has a combination
-+ * of allocated and free inodes or is completely free and ikeep
-+ * is enabled. Update the record.
-+ */
-+ 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_bmap_free *flist, /* extents to free */
-+ int *deleted,/* set if inode cluster was deleted */
-+ xfs_ino_t *first_ino)/* first inode in deleted cluster */
-+{
-+ /* 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 XFS_ERROR(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 XFS_ERROR(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 XFS_ERROR(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, flist, deleted, first_ino,
-+ &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,
-@@ -1271,7 +1667,7 @@ xfs_imap_lookup(
- * 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);
-+ 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)
-@@ -1482,6 +1878,8 @@ xfs_ialloc_log_agi(
- 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
-@@ -1491,14 +1889,39 @@ xfs_ialloc_log_agi(
- ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC));
- #endif
- /*
-- * Compute byte offsets for the first and last fields.
-+ * The growth of the agi buffer over time now requires that we interpret
-+ * the buffer as two logical regions delineated at 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.
- */
-- xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS, &first, &last);
-+ xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGI_BUF);
-+
- /*
-- * Log the allocation group inode header buffer.
-+ * Compute byte offsets for the first and last fields in the first
-+ * region and log agi buffer. This only logs up through agi_unlinked.
- */
-- xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGI_BUF);
-- xfs_trans_log_buf(tp, bp, first, last);
-+ 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
-diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c
-index 0a29d73..c337389 100644
---- a/libxfs/xfs_ialloc_btree.c
-+++ b/libxfs/xfs_ialloc_btree.c
-@@ -30,7 +30,8 @@ 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_private.a.agbp, cur->bc_private.a.agno,
-+ cur->bc_btnum);
- }
-
- STATIC void
-@@ -47,6 +48,21 @@ xfs_inobt_set_root(
- 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,
-@@ -154,6 +170,17 @@ xfs_inobt_init_ptr_from_cur(
- 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,
-@@ -184,6 +211,7 @@ xfs_inobt_verify(
- */
- 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 (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid))
-@@ -195,6 +223,7 @@ xfs_inobt_verify(
- return false;
- /* fall through */
- case cpu_to_be32(XFS_IBT_MAGIC):
-+ case cpu_to_be32(XFS_FIBT_MAGIC):
- break;
- default:
- return 0;
-@@ -371,6 +400,28 @@ static const struct xfs_btree_ops xfs_inobt_ops = {
- #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_key = xfs_inobt_init_rec_from_key,
-+ .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.
- */
-@@ -379,7 +430,8 @@ 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_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;
-@@ -388,11 +440,17 @@ xfs_inobt_init_cursor(
-
- cur->bc_tp = tp;
- cur->bc_mp = mp;
-- cur->bc_nlevels = be32_to_cpu(agi->agi_level);
-- cur->bc_btnum = XFS_BTNUM_INO;
-+ 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;
-
-- cur->bc_ops = &xfs_inobt_ops;
- if (xfs_sb_version_hascrc(&mp->m_sb))
- cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
-
-diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
-index 7ee4612..ea89367 100644
---- a/libxfs/xfs_sb.c
-+++ b/libxfs/xfs_sb.c
-@@ -408,6 +408,8 @@ xfs_sb_from_disk(
- 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_pad = 0;
- to->sb_pquotino = be64_to_cpu(from->sb_pquotino);
- to->sb_lsn = be64_to_cpu(from->sb_lsn);
-@@ -485,6 +487,9 @@ xfs_sb_to_disk(
- if (!fields)
- return;
-
-+ /* We should never write the crc here, it's updated in the IO path */
-+ fields &= ~XFS_SB_CRC;
-+
- xfs_sb_quota_to_disk(to, from, &fields);
- while (fields) {
- f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
-diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c
-index 1e59fad..870d4fc 100644
---- a/libxfs/xfs_trans_resv.c
-+++ b/libxfs/xfs_trans_resv.c
-@@ -81,6 +81,37 @@ xfs_calc_inode_res(
- }
-
- /*
-+ * 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.
-+ * Therefore, a record can be removed from the tree for an inode allocation or
-+ * free and the associated merge reservation is unconditional. This also covers
-+ * the possibility of a split on record insertion.
-+ *
-+ * the free inode btree: max depth * block size
-+ * the free inode btree entry: block size
-+ *
-+ * TODO: is the modify res really necessary? covered by the merge/split res?
-+ * This seems to be the pattern of ifree, but not create_resv_alloc. Why?
-+ */
-+STATIC uint
-+xfs_calc_finobt_res(
-+ struct xfs_mount *mp,
-+ 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 (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
-@@ -250,6 +281,7 @@ xfs_calc_remove_reservation(
- * 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
- */
- STATIC uint
- xfs_calc_create_resv_modify(
-@@ -258,7 +290,8 @@ xfs_calc_create_resv_modify(
- 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_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1)) +
-+ xfs_calc_finobt_res(mp, 1);
- }
-
- /*
-@@ -268,6 +301,7 @@ xfs_calc_create_resv_modify(
- * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize
- * the inode btree: max depth * blocksize
- * the allocation btrees: 2 trees * (max depth - 1) * block size
-+ * the finobt
- */
- STATIC uint
- xfs_calc_create_resv_alloc(
-@@ -278,7 +312,8 @@ xfs_calc_create_resv_alloc(
- xfs_calc_buf_res(XFS_IALLOC_BLOCKS(mp), 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));
-+ XFS_FSB_TO_B(mp, 1)) +
-+ xfs_calc_finobt_res(mp, 0);
- }
-
- STATIC uint
-@@ -296,6 +331,7 @@ __xfs_calc_create_reservation(
- * 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
- */
- STATIC uint
- xfs_calc_icreate_resv_alloc(
-@@ -305,7 +341,8 @@ xfs_calc_icreate_resv_alloc(
- 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_FSB_TO_B(mp, 1)) +
-+ xfs_calc_finobt_res(mp, 0);
- }
-
- STATIC uint
-@@ -359,6 +396,7 @@ xfs_calc_symlink_reservation(
- * 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
- */
- STATIC uint
- xfs_calc_ifree_reservation(
-@@ -374,7 +412,8 @@ xfs_calc_ifree_reservation(
- xfs_calc_buf_res(2 + XFS_IALLOC_BLOCKS(mp) +
- mp->m_in_maxlevels, 0) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
-- XFS_FSB_TO_B(mp, 1));
-+ XFS_FSB_TO_B(mp, 1)) +
-+ xfs_calc_finobt_res(mp, 1);
- }
-
- /*
-diff --git a/man/man5/xfs.5 b/man/man5/xfs.5
-index 0f490f0..5e47c4c 100644
---- a/man/man5/xfs.5
-+++ b/man/man5/xfs.5
-@@ -1,6 +1,6 @@
- .TH xfs 5
- .SH NAME
--xfs \- layout of the XFS filesystem
-+xfs \- layout and mount options for the XFS filesystem
- .SH DESCRIPTION
- An XFS filesystem can reside on a regular disk partition or on a
- logical volume.
-@@ -98,9 +98,210 @@ and by-handle (see
- .BR open_by_handle (3))
- interfaces.
- .SH MOUNT OPTIONS
--Refer to the
-+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 entry for descriptions of the individual XFS mount options.
-+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/uqnoenforce/quota
-+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 SEE ALSO
- .BR xfsctl (3),
- .BR mount (8),
-diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
-index 8184e10..ad9ff3d 100644
---- a/man/man8/mkfs.xfs.8
-+++ b/man/man8/mkfs.xfs.8
-@@ -7,6 +7,9 @@ mkfs.xfs \- construct an XFS filesystem
- .B \-b
- .I block_size
- ] [
-+.B \-m
-+.I global_metadata_options
-+] [
- .B \-d
- .I data_section_options
- ] [
-@@ -125,6 +128,48 @@ The default value is 4096 bytes (4 KiB), the minimum is 512, and the
- maximum is 65536 (64 KiB).
- XFS on Linux currently only supports 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 noticable in normal operation.
-+.IP
-+By default,
-+.B mkfs.xfs
-+will not 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 not create free inode btrees. This feature is also currently only available
-+for filesystems created with the
-+.B \-m crc=1
-+option set.
-+.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
-diff --git a/man/man8/xfs_check.8 b/man/man8/xfs_check.8
-deleted file mode 100644
-index 23027ca..0000000
---- a/man/man8/xfs_check.8
-+++ /dev/null
-@@ -1,203 +0,0 @@
--.TH xfs_check 8
--.SH NAME
--xfs_check \- check XFS filesystem consistency
--.SH SYNOPSIS
--.B xfs_check
--[
--.B \-i
--.I ino
--] ... [
--.B \-b
--.I bno
--] ... [
--.B \-f
--] [
--.B \-s
--] [
--.B \-v
--] [
--.B \-l
--.I logdev
--]
--.I device
--.br
--.B xfs_check \-V
--.SH DESCRIPTION
--.B xfs_check
--checks whether an XFS filesystem is consistent.
--It is normally run only when there is reason to believe that the
--filesystem has a consistency problem.
--The filesystem to be checked 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. The filesystem should normally be unmounted or read-only
--during the execution of
--.BR xfs_check .
--Otherwise, spurious problems are reported.
--.PP
--Note that
--.B xfs_check
--is deprecated and scheduled for removal in June 2014. Please use
--.BR xfs_repair " " \-n
--instead.
--.SH
--OPTIONS
--.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.
--.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
--.BR mkfs.xfs "(8) " \-l
--option, and refer to
--.BR xfs (5)
--for a detailed description of the XFS log.
--.TP
--.B \-s
--Specifies that only serious errors should be reported.
--Serious errors are those that make it impossible to find major data
--structures in the filesystem. This option can be used to cut down the
--amount of output when there is a serious problem, when the output
--might make it difficult to see what the real problem is.
--.TP
--.B \-v
--Specifies verbose output; it is impossibly long for a
--reasonably-sized filesystem.
--This option is intended for internal use only.
--.TP
--.BI \-i " ino"
--Specifies verbose behavior for the specified inode
--.IR ino .
--For instance, it can be used to locate all the blocks
--associated with a given inode.
--.TP
--.BI \-b " bno"
--Specifies verbose behavior for the specific filesystem block at
--.IR bno .
--For instance, it can be used to determine what a specific block
--is used for. The block number is a "file system block number".
--Conversion between disk addresses (i.e. addresses reported by
--.BR xfs_bmap (8))
--and file system blocks may be accomplished using
--.BR xfs_db "(8)'s " convert
--command.
--.TP
--.B \-V
--Prints the version number and exits.
--.PP
--Any output that is produced when
--.B xfs_check
--is not run in verbose mode indicates that the filesystem has an
--inconsistency. The filesystem can be repaired using either
--.BR xfs_repair (8)
--to fix the filesystem in place, or by using
--.BR xfsdump (8)
--and
--.BR mkfs.xfs (8)
--to dump the filesystem, make a new filesystem, then use
--.BR xfsrestore (8)
--to restore the data onto the new filesystem.
--Note that xfsdump may fail on a corrupt filesystem.
--However, if the filesystem is mountable, xfsdump can
--be used to try and save important data before
--repairing the filesystem with xfs_repair.
--If the filesystem is not mountable though, xfs_repair is
--the only viable option.
--.SH DIAGNOSTICS
--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 xfs_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
--The block is unaccounted for (not in the freelist and not in use).
--.TP
--.BI "link count mismatch for inode " nnn " (name " xxx "), nlink " m ", counted " n
--The inode has a bad link count (number of references in directories).
--.TP
--.BI "rtblock " b " expected inum 0 got " i
--The block is used multiple times (shared), between multiple inodes.
--This message usually follows a message of the next type.
--.TP
--.BI "rtblock " b " expected type unknown got " y
--The real-time block is used multiple times (shared).
--.TP
--.BI "rtblock " b " type unknown not expected
--The real-time block is unaccounted for (not in the freelist and not in use).
--.TP
--.BI "sb_fdblocks " n ", counted " m
--The number of free data blocks recorded
--in the superblock doesn't match the number counted free in the filesystem.
--.TP
--.BI "sb_frextents " n ", counted " m
--The number of free real-time extents recorded
--in the superblock doesn't match the number counted free in the filesystem.
--.TP
--.BI "sb_icount " n ", counted " m
--The number of allocated inodes recorded
--in the superblock doesn't match the number allocated in the filesystem.
--.TP
--.BI "sb_ifree " n ", counted " m
--The number of free inodes recorded
--in the superblock doesn't match the number free in the filesystem.
--.SH SEE ALSO
--.BR mkfs.xfs (8),
--.BR xfsdump (8),
--.BR xfsrestore (8),
--.BR xfs_ncheck (8),
--.BR xfs_repair (8),
--.BR xfs (5).
-diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8
-index 7a43a2c..4d8d4ff 100644
---- a/man/man8/xfs_db.8
-+++ b/man/man8/xfs_db.8
-@@ -38,8 +38,7 @@ 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. This is the mechanism used to implement
--.BR xfs_check (8).
-+then the program exits.
- .TP
- .B \-f
- Specifies that the filesystem image to be processed is stored in a
-@@ -56,14 +55,11 @@ an ordinary file with
- .B \-F
- Specifies that we want to continue even if the superblock magic is not
- correct. For use in
--.BR xfs_check
--and
- .BR xfs_metadump .
- .TP
- .B \-i
- Allows execution on a mounted filesystem, provided it is mounted read-only.
--Useful for shell scripts such as
--.BR xfs_check (8),
-+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
-@@ -204,9 +200,7 @@ command can be given, presumably with different arguments than the previous one.
- Get block usage and check filesystem consistency.
- The information is saved for use by a subsequent
- .BR blockuse ", " ncheck ", or " blocktrash
--command. See
--.BR xfs_check (8)
--for more information.
-+command.
- .RS 1.0i
- .TP 0.4i
- .B \-b
-@@ -244,7 +238,7 @@ 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) and " xfs_check (8).
-+.BR xfs_repair "(8).
- .RS 1.0i
- .TP 0.4i
- .BR \-0 " | " -1 " | " -2 " | " -3
-@@ -1856,12 +1850,60 @@ and printable ASCII chars.
- Many messages can come from the
- .B check
- .RB ( blockget )
--command; these are documented in
--.BR xfs_check (8).
-+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_check (8),
- .BR xfs_copy (8),
- .BR xfs_logprint (8),
- .BR xfs_metadump (8),
-diff --git a/man/man8/xfs_mdrestore.8 b/man/man8/xfs_mdrestore.8
-index 51297c4..0957d81 100644
---- a/man/man8/xfs_mdrestore.8
-+++ b/man/man8/xfs_mdrestore.8
-@@ -48,7 +48,6 @@ returns an exit code of 0 if all the metadata is successfully restored or
- .SH SEE ALSO
- .BR xfs_metadump (8),
- .BR xfs_repair (8),
--.BR xfs_check (8),
- .BR xfs (5)
- .SH BUGS
- Email bug reports to
-diff --git a/man/man8/xfs_ncheck.8 b/man/man8/xfs_ncheck.8
-index 4099772..5ae72b2 100644
---- a/man/man8/xfs_ncheck.8
-+++ b/man/man8/xfs_ncheck.8
-@@ -63,13 +63,12 @@ May be given multiple times to select multiple inode numbers.
- 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
--.BR xfs_check (8)
--may appear.
-+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_check (8),
- .BR xfs (5).
-diff --git a/man/man8/xfs_repair.8 b/man/man8/xfs_repair.8
-index b7c2d8c..0394c50 100644
---- a/man/man8/xfs_repair.8
-+++ b/man/man8/xfs_repair.8
-@@ -548,6 +548,5 @@ fixed and/or improved.
- .BR mkfs.xfs (8),
- .BR umount (8),
- .BR xfs_admin (8),
--.BR xfs_check (8),
- .BR xfs_metadump (8),
- .BR xfs (5).
-diff --git a/mkfs/proto.c b/mkfs/proto.c
-index 5a47e27..72068f0 100644
---- a/mkfs/proto.c
-+++ b/mkfs/proto.c
-@@ -197,7 +197,6 @@ rsvfile(
- tp = libxfs_trans_alloc(mp, 0);
-
- libxfs_trans_ijoin(tp, ip, 0);
-- libxfs_trans_ihold(tp, ip);
-
- ip->i_d.di_mode &= ~S_ISUID;
-
-@@ -464,7 +463,6 @@ parseproto(
- libxfs_trans_ijoin(tp, pip, 0);
- xname.type = XFS_DIR3_FT_REG_FILE;
- newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
-- libxfs_trans_ihold(tp, pip);
- break;
-
- case IF_RESERVED: /* pre-allocated space only */
-@@ -481,7 +479,6 @@ parseproto(
-
- xname.type = XFS_DIR3_FT_REG_FILE;
- newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
-- libxfs_trans_ihold(tp, pip);
- libxfs_trans_log_inode(tp, ip, flags);
-
- error = libxfs_bmap_finish(&tp, &flist, &committed);
-@@ -489,6 +486,7 @@ parseproto(
- fail(_("Pre-allocated file creation failed"), error);
- libxfs_trans_commit(tp, 0);
- rsvfile(mp, ip, llen);
-+ IRELE(ip);
- return;
-
- case IF_BLOCK:
-@@ -503,7 +501,6 @@ parseproto(
- libxfs_trans_ijoin(tp, pip, 0);
- xname.type = XFS_DIR3_FT_BLKDEV;
- newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
-- libxfs_trans_ihold(tp, pip);
- flags |= XFS_ILOG_DEV;
- break;
-
-@@ -518,7 +515,6 @@ parseproto(
- libxfs_trans_ijoin(tp, pip, 0);
- xname.type = XFS_DIR3_FT_CHRDEV;
- newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
-- libxfs_trans_ihold(tp, pip);
- flags |= XFS_ILOG_DEV;
- break;
-
-@@ -531,7 +527,6 @@ parseproto(
- libxfs_trans_ijoin(tp, pip, 0);
- xname.type = XFS_DIR3_FT_FIFO;
- newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
-- libxfs_trans_ihold(tp, pip);
- break;
- case IF_SYMLINK:
- buf = getstr(pp);
-@@ -545,7 +540,6 @@ parseproto(
- libxfs_trans_ijoin(tp, pip, 0);
- xname.type = XFS_DIR3_FT_SYMLINK;
- newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist);
-- libxfs_trans_ihold(tp, pip);
- break;
- case IF_DIRECTORY:
- getres(tp, 0);
-@@ -565,7 +559,6 @@ parseproto(
- newdirent(mp, tp, pip, &xname, ip->i_ino,
- &first, &flist);
- pip->i_d.di_nlink++;
-- libxfs_trans_ihold(tp, pip);
- libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE);
- }
- newdirectory(mp, tp, ip, pip);
-@@ -573,7 +566,6 @@ parseproto(
- error = libxfs_bmap_finish(&tp, &flist, &committed);
- if (error)
- fail(_("Directory creation failed"), error);
-- libxfs_trans_ihold(tp, ip);
- libxfs_trans_commit(tp, 0);
- /*
- * RT initialization. Do this here to ensure that
-@@ -590,7 +582,7 @@ parseproto(
- break;
- parseproto(mp, ip, fsxp, pp, name);
- }
-- libxfs_iput(ip, 0);
-+ IRELE(ip);
- return;
- default:
- ASSERT(0);
-@@ -603,6 +595,7 @@ parseproto(
- error);
- }
- libxfs_trans_commit(tp, 0);
-+ IRELE(ip);
- }
-
- void
-@@ -665,7 +658,6 @@ rtinit(
- *(__uint64_t *)&rbmip->i_d.di_atime = 0;
- libxfs_trans_log_inode(tp, rbmip, XFS_ILOG_CORE);
- libxfs_mod_sb(tp, XFS_SB_RBMINO);
-- libxfs_trans_ihold(tp, rbmip);
- mp->m_rbmip = rbmip;
- error = libxfs_inode_alloc(&tp, NULL, S_IFREG, 1, 0,
- &creds, &fsxattrs, &rsumip);
-@@ -676,7 +668,6 @@ rtinit(
- rsumip->i_d.di_size = mp->m_rsumsize;
- libxfs_trans_log_inode(tp, rsumip, XFS_ILOG_CORE);
- libxfs_mod_sb(tp, XFS_SB_RSUMINO);
-- libxfs_trans_ihold(tp, rsumip);
- libxfs_trans_commit(tp, 0);
- mp->m_rsumip = rsumip;
- /*
-@@ -689,7 +680,6 @@ rtinit(
- res_failed(i);
-
- libxfs_trans_ijoin(tp, rbmip, 0);
-- libxfs_trans_ihold(tp, rbmip);
- bno = 0;
- xfs_bmap_init(&flist, &first);
- while (bno < mp->m_sb.sb_rbmblocks) {
-@@ -726,7 +716,6 @@ rtinit(
- if (i)
- res_failed(i);
- libxfs_trans_ijoin(tp, rsumip, 0);
-- libxfs_trans_ihold(tp, rsumip);
- bno = 0;
- xfs_bmap_init(&flist, &first);
- while (bno < nsumblocks) {
-@@ -762,7 +751,6 @@ rtinit(
- if (i)
- res_failed(i);
- libxfs_trans_ijoin(tp, rbmip, 0);
-- libxfs_trans_ihold(tp, rbmip);
- xfs_bmap_init(&flist, &first);
- ebno = XFS_RTMIN(mp->m_sb.sb_rextents,
- bno + NBBY * mp->m_sb.sb_blocksize);
-diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
-index 37c05a9..c85258a 100644
---- a/mkfs/xfs_mkfs.c
-+++ b/mkfs/xfs_mkfs.c
-@@ -183,6 +183,8 @@ char *sopts[] = {
- char *mopts[] = {
- #define M_CRC 0
- "crc",
-+#define M_FINOBT 1
-+ "finobt",
- NULL
- };
-
-@@ -455,11 +457,30 @@ static void get_topology(
- int force_overwrite)
- {
- if (!xi->disfile) {
-- const char *dfile = xi->volname ? xi->volname : xi->dname;
-+ char *dfile = xi->volname ? xi->volname : xi->dname;
-+ struct stat statbuf;
-
-- blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
-- &ft->lsectorsize, &ft->psectorsize,
-- force_overwrite);
-+ /*
-+ * If our target is a regular file, and xi->disfile isn't
-+ * set (i.e. no "-d file" invocation), 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 (!stat(dfile, &statbuf) && S_ISREG(statbuf.st_mode)) {
-+ int fd;
-+ long long dummy;
-+
-+ fd = open(dfile, O_RDONLY);
-+ if (fd >= 0) {
-+ platform_findsizes(dfile, fd, &dummy,
-+ &ft->lsectorsize);
-+ close(fd);
-+ }
-+ } else {
-+ blkid_get_topology(dfile, &ft->dsunit, &ft->dswidth,
-+ &ft->lsectorsize, &ft->psectorsize,
-+ force_overwrite);
-+ }
- }
-
- if (xi->rtname && !xi->risfile) {
-@@ -962,6 +983,7 @@ main(
- struct fs_topology ft;
- int lazy_sb_counters;
- int crcs_enabled;
-+ int finobt;
-
- progname = basename(argv[0]);
- setlocale(LC_ALL, "");
-@@ -995,6 +1017,7 @@ main(
- worst_freelist = 0;
- lazy_sb_counters = 1;
- crcs_enabled = 0;
-+ finobt = 0;
- memset(&fsx, 0, sizeof(fsx));
-
- memset(&xi, 0, sizeof(xi));
-@@ -1486,6 +1509,14 @@ _("cannot specify both crc and ftype\n"));
- usage();
- }
- break;
-+ case M_FINOBT:
-+ if (!value || *value == '\0')
-+ reqval('m', mopts, M_CRC);
-+ c = atoi(value);
-+ if (c < 0 || c > 1)
-+ illegal(value, "m finobt");
-+ finobt = c;
-+ break;
- default:
- unknown('m', value);
- }
-@@ -1827,6 +1858,16 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
- }
- }
-
-+ /*
-+ * The kernel doesn't currently support crc=0,finobt=1 filesystems.
-+ * Catch it here, disable finobt and warn the user.
-+ */
-+ if (finobt && !crcs_enabled) {
-+ fprintf(stderr,
-+_("warning: finobt not supported without CRC support, disabled.\n"));
-+ finobt = 0;
-+ }
-+
- if (nsflag || nlflag) {
- if (dirblocksize < blocksize ||
- dirblocksize > XFS_MAX_BLOCKSIZE) {
-@@ -2413,6 +2454,30 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
- mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
- mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
-
-+ /*
-+ * sb_versionnum and finobt flags must be set before we use
-+ * XFS_PREALLOC_BLOCKS().
-+ */
-+ sbp->sb_features2 = XFS_SB_VERSION2_MKFS(crcs_enabled, lazy_sb_counters,
-+ attrversion == 2, !projid16bit, 0,
-+ (!crcs_enabled && dirftype));
-+ sbp->sb_versionnum = XFS_SB_VERSION_MKFS(crcs_enabled, iaflag,
-+ dsunit != 0,
-+ logversion == 2, attrversion == 1,
-+ (sectorsize != BBSIZE ||
-+ lsectorsize != BBSIZE),
-+ nci, sbp->sb_features2 != 0);
-+ /*
-+ * 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 (finobt)
-+ sbp->sb_features_ro_compat = XFS_SB_FEAT_RO_COMPAT_FINOBT;
-+
- if (loginternal) {
- /*
- * Readjust the log size to fit within an AG if it was sized
-@@ -2475,7 +2540,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
- printf(_(
- "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
- " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n"
-- " =%-22s crc=%u\n"
-+ " =%-22s crc=%-8u finobt=%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"
-@@ -2484,7 +2549,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
- "realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"),
- dfile, isize, (long long)agcount, (long long)agsize,
- "", sectorsize, attrversion, !projid16bit,
-- "", crcs_enabled,
-+ "", crcs_enabled, finobt,
- "", blocksize, (long long)dblocks, imaxpct,
- "", dsunit, dswidth,
- dirversion, dirblocksize, nci, dirftype,
-@@ -2553,23 +2618,6 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
- sbp->sb_logsectsize = 0;
- }
-
-- sbp->sb_features2 = XFS_SB_VERSION2_MKFS(crcs_enabled, lazy_sb_counters,
-- attrversion == 2, !projid16bit, 0,
-- (!crcs_enabled && dirftype));
-- sbp->sb_versionnum = XFS_SB_VERSION_MKFS(crcs_enabled, iaflag,
-- dsunit != 0,
-- logversion == 2, attrversion == 1,
-- (sectorsize != BBSIZE ||
-- lsectorsize != BBSIZE),
-- nci, sbp->sb_features2 != 0);
-- /*
-- * 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 (force_overwrite)
- zero_old_xfs_structures(&xi, sbp);
-
-@@ -2726,6 +2774,10 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
- agi->agi_count = 0;
- agi->agi_root = cpu_to_be32(XFS_IBT_BLOCK(mp));
- agi->agi_level = cpu_to_be32(1);
-+ if (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);
-@@ -2851,6 +2903,26 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
- xfs_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 (!finobt)
-+ continue;
-+
-+ 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))
-+ xfs_btree_init_block(mp, buf, XFS_FIBT_CRC_MAGIC, 0, 0,
-+ agno, XFS_BTREE_CRC_BLOCKS);
-+ else
-+ xfs_btree_init_block(mp, buf, XFS_FIBT_MAGIC, 0, 0,
-+ agno, 0);
-+ libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
- }
-
- /*
-@@ -3087,7 +3159,7 @@ usage( void )
- {
- fprintf(stderr, _("Usage: %s\n\
- /* blocksize */ [-b log=n|size=num]\n\
--/* metadata */ [-m crc=[0|1]\n\
-+/* metadata */ [-m crc=0|1,finobt=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\
-diff --git a/po/pl.po b/po/pl.po
-index ebd1884..80a09a8 100644
---- a/po/pl.po
-+++ b/po/pl.po
-@@ -1,13 +1,13 @@
- # Polish translation for xfsprogs.
- # This file is distributed under the same license as the xfsprogs package.
--# Jakub Bogusz <qboosh at pld-linux.org>, 2006-2012.
-+# Jakub Bogusz <qboosh at pld-linux.org>, 2006-2014.
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: xfsprogs 3.1.8\n"
-+"Project-Id-Version: xfsprogs 3.2.0\n"
- "Report-Msgid-Bugs-To: \n"
--"POT-Creation-Date: 2012-03-04 06:24+0100\n"
--"PO-Revision-Date: 2012-03-04 07:30+0100\n"
-+"POT-Creation-Date: 2014-05-21 18:34+0200\n"
-+"PO-Revision-Date: 2014-05-21 18:41+0200\n"
- "Last-Translator: Jakub Bogusz <qboosh at pld-linux.org>\n"
- "Language-Team: Polish <translation-team-pl at lists.sourceforge.net>\n"
- "Language: pl\n"
-@@ -15,6611 +15,6890 @@ msgstr ""
- "Content-Type: text/plain; charset=UTF-8\n"
- "Content-Transfer-Encoding: 8bit\n"
-
--#: .././rtcp/xfs_rtcp.c:30
-+#: .././copy/xfs_copy.c:102
- #, c-format
--msgid "%s [-e extsize] [-p] source target\n"
--msgstr "%s [-e rozm_fragmentu] [-p] źródło cel\n"
-+msgid "Check logfile \"%s\" for more details\n"
-+msgstr "Więcej szczegółów w pliku logu \"%s\"\n"
-
--#: .././rtcp/xfs_rtcp.c:55 .././repair/xfs_repair.c:317 .././quota/init.c:131
--#: .././mkfs/xfs_mkfs.c:1623 .././logprint/logprint.c:196 .././io/init.c:183
--#: .././growfs/xfs_growfs.c:182 .././fsr/xfs_fsr.c:302
--#: .././estimate/xfs_estimate.c:141 .././db/init.c:93 .././copy/xfs_copy.c:543
-+#: .././copy/xfs_copy.c:108
- #, c-format
--msgid "%s version %s\n"
--msgstr "%s wersja %s\n"
-+msgid "%s: could not write to logfile \"%s\".\n"
-+msgstr "%s: nie udało się zapisać pliku logu \"%s\".\n"
-
--#: .././rtcp/xfs_rtcp.c:69
-+#: .././copy/xfs_copy.c:111
- #, c-format
--msgid "%s: must specify files to copy\n"
--msgstr "%s: trzeba podać pliki do skopiowania\n"
-+msgid "Aborting XFS copy -- logfile error -- reason: %s\n"
-+msgstr "Przerwano XFS copy - błąd pliku logu - przyczyna: %s\n"
-
--#: .././rtcp/xfs_rtcp.c:84
--#, c-format
--msgid "%s: stat64 of %s failed\n"
--msgstr "%s: stat64 na %s nie powiodło się\n"
-+#: .././copy/xfs_copy.c:126 .././copy/xfs_copy.c:286 .././copy/xfs_copy.c:566
-+#: .././copy/xfs_copy.c:573
-+msgid "Aborting XFS copy - reason"
-+msgstr "Przerwano XFS copy - przyczyna"
-
--#: .././rtcp/xfs_rtcp.c:91
--#, c-format
--msgid "%s: final argument is not directory\n"
--msgstr "%s: ostatni argument nie jest katalogiem\n"
-+#: .././copy/xfs_copy.c:140
-+msgid "THE FOLLOWING COPIES FAILED TO COMPLETE\n"
-+msgstr "NASTĘPUJĄCYCH KOPII NIE UDAŁO SIĘ UKOŃCZYĆ\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"
-+#: .././copy/xfs_copy.c:144
-+msgid "write error"
-+msgstr "błąd zapisu"
-
--#: .././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"
-+#: .././copy/xfs_copy.c:146
-+msgid "lseek64 error"
-+msgstr "błąd lseek64"
-
--#: .././rtcp/xfs_rtcp.c:180 .././rtcp/xfs_rtcp.c:208
-+#: .././copy/xfs_copy.c:147
- #, c-format
--msgid "%s: open of %s failed: %s\n"
--msgstr "%s: otwarcie %s nie powiodło się: %s\n"
-+msgid " at offset %lld\n"
-+msgstr " pod offsetem %lld\n"
-
--#: .././rtcp/xfs_rtcp.c:197
-+#: .././copy/xfs_copy.c:151
- #, c-format
--msgid "%s: set attributes on %s failed: %s\n"
--msgstr "%s: ustawienie atrybutów dla %s nie powiodło się: %s\n"
-+msgid "All copies completed.\n"
-+msgstr "Wszystkie kopie ukończone.\n"
-
--#: .././rtcp/xfs_rtcp.c:215
-+#: .././copy/xfs_copy.c:154
- #, c-format
--msgid "%s: get attributes of %s failed: %s\n"
--msgstr "%s: pobranie atrybutów %s nie powiodło się: %s\n"
-+msgid "See \"%s\" for more details.\n"
-+msgstr "Więcej szczegółów w \"%s\".\n"
-
--#: .././rtcp/xfs_rtcp.c:225 .././rtcp/xfs_rtcp.c:260
-+#: .././copy/xfs_copy.c:255
- #, c-format
--msgid "%s: %s is not a realtime file.\n"
--msgstr "%s: %s nie jest plikiem realtime.\n"
-+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"
-
--#: .././rtcp/xfs_rtcp.c:234
-+#: .././copy/xfs_copy.c:260
- #, 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"
-+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"
-
--#: .././rtcp/xfs_rtcp.c:246 .././rtcp/xfs_rtcp.c:269
-+#: .././copy/xfs_copy.c:266
- #, c-format
--msgid "%s: open of %s source failed: %s\n"
--msgstr "%s: otwarcie źródła %s nie powiodło się: %s\n"
-+msgid "Aborting target %d - reason"
-+msgstr "Przerywano zapis celu %d - przyczyna"
-
--#: .././rtcp/xfs_rtcp.c:283
--#, 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"
-+#: .././copy/xfs_copy.c:270
-+msgid "Aborting XFS copy - no more targets.\n"
-+msgstr "Przerwano XFS copy - nie ma więcej celów.\n"
-
--#: .././rtcp/xfs_rtcp.c:293
-+#: .././copy/xfs_copy.c:281
- #, c-format
--msgid "%s: extent size %d not a multiple of %d.\n"
--msgstr "%s: rozmiar ekstentu %d nie jest wielokrotnością %d.\n"
-+msgid "%s: thread %d died unexpectedly, target \"%s\" incomplete\n"
-+msgstr "%s: wątek %d zmarł nieoczekiwanie, cel \"%s\" niekompletny\n"
-
--#: .././rtcp/xfs_rtcp.c:307
-+#: .././copy/xfs_copy.c:283
- #, c-format
--msgid "The size of %s is not a multiple of %d.\n"
--msgstr "Rozmiar %s nie jest wielokrotnością %d.\n"
-+msgid "%s: offset was probably %lld\n"
-+msgstr "%s: offset prawdopodobnie %lld\n"
-
--#: .././rtcp/xfs_rtcp.c:310
-+#: .././copy/xfs_copy.c:294
- #, c-format
--msgid "%s will be padded to %lld bytes.\n"
--msgstr "%s: zostanie dopełniony do %lld bajtów.\n"
-+msgid "%s: Unknown child died (should never happen!)\n"
-+msgstr "%s: Nieznany potomek zmarł (nie powinno się zdarzyć!)\n"
-
--#: .././rtcp/xfs_rtcp.c:316
-+#: .././copy/xfs_copy.c:304
- #, 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"
-+msgid "Usage: %s [-bdV] [-L logfile] source target [target ...]\n"
-+msgstr "Składnia: %s [-bdV] [-L plik_logu] źródło cel [cel ...]\n"
-
--#: .././rtcp/xfs_rtcp.c:358
-+#: .././copy/xfs_copy.c:386
- #, c-format
--msgid "%s: write error: %s\n"
--msgstr "%s: błąd zapisu: %s\n"
-+msgid "%s: lseek64 failure at offset %lld\n"
-+msgstr "%s: niepowodzenie lseek64 pod offsetem %lld\n"
-
--#: .././rtcp/xfs_rtcp.c:386
-+#: .././copy/xfs_copy.c:401
- #, c-format
--msgid "%s: could not open %s: %s\n"
--msgstr "%s: nie udało się otworzyć %s: %s\n"
-+msgid "assert error: buf->length = %d, buf->size = %d\n"
-+msgstr "błąd zapewnienia: buf->length = %d, buf->size = %d\n"
-
--#: .././repair/xfs_repair.c:81
-+#: .././copy/xfs_copy.c:408
- #, 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 minutes.\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:107
--msgid "no error"
--msgstr "brak błędu"
--
--#: .././repair/xfs_repair.c:108
--msgid "bad magic number"
--msgstr "błędna liczba magiczna"
--
--#: .././repair/xfs_repair.c:109
--msgid "bad blocksize field"
--msgstr "błędne pole blocksize"
--
--#: .././repair/xfs_repair.c:110
--msgid "bad blocksize log field"
--msgstr "błędne pole logu blocksize"
--
--#: .././repair/xfs_repair.c:111
--msgid "bad or unsupported version"
--msgstr "błędna lub nie obsługiwana wersja"
--
--#: .././repair/xfs_repair.c:113
--msgid "filesystem mkfs-in-progress bit set"
--msgstr "ustawiony bit mkfs-in-progress systemu plików"
-+msgid "%s: read failure at offset %lld\n"
-+msgstr "%s: błąd odczytu pod offsetem %lld\n"
-
--#: .././repair/xfs_repair.c:115
--msgid "inconsistent filesystem geometry information"
--msgstr "niespójne informacje o geometrii systemu plików"
-+#: .././copy/xfs_copy.c:438
-+msgid "ag header buffer invalid!\n"
-+msgstr "błędny bufor nagłówka ag!\n"
-
--#: .././repair/xfs_repair.c:117
--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"
-+#: .././copy/xfs_copy.c:546 .././db/init.c:94 .././estimate/xfs_estimate.c:144
-+#: .././fsr/xfs_fsr.c:300 .././growfs/xfs_growfs.c:180 .././io/init.c:190
-+#: .././logprint/logprint.c:203 .././mkfs/xfs_mkfs.c:1672
-+#: .././quota/init.c:131 .././repair/xfs_repair.c:319 .././rtcp/xfs_rtcp.c:55
-+#, c-format
-+msgid "%s version %s\n"
-+msgstr "%s wersja %s\n"
-
--#: .././repair/xfs_repair.c:118
--msgid "bad sector size"
--msgstr "błędny rozmiar sektora"
-+#: .././copy/xfs_copy.c:564
-+#, c-format
-+msgid "%s: couldn't open log file \"%s\"\n"
-+msgstr "%s: nie udało się otworzyć pliku logu \"%s\"\n"
-
--#: .././repair/xfs_repair.c:120
--msgid "AGF geometry info conflicts with filesystem geometry"
--msgstr "informacje o geometrii AGF są w konflikcie z geometrią systemu plików"
-+#: .././copy/xfs_copy.c:571
-+#, c-format
-+msgid "%s: couldn't set up logfile stream\n"
-+msgstr "%s: nie udało się ustanowić strumienia pliku logu\n"
-
--#: .././repair/xfs_repair.c:122
--msgid "AGI geometry info conflicts with filesystem geometry"
--msgstr "informacje o geometrii AGI są w konflikcie z geometrią systemu plików"
-+#: .././copy/xfs_copy.c:583
-+msgid "Couldn't allocate target array\n"
-+msgstr "Nie udało się przydzielić tablicy celów\n"
-
--#: .././repair/xfs_repair.c:124
--msgid "AG superblock geometry info conflicts with filesystem geometry"
--msgstr "informacje o geometrii superbloku AG są w konflikcie z geometrią systemu plików"
-+#: .././copy/xfs_copy.c:598
-+#, c-format
-+msgid "%s: couldn't register atexit function.\n"
-+msgstr "%s: nie udało się zarejestrować funkcji atexit.\n"
-
--#: .././repair/xfs_repair.c:125
--msgid "attempted to perform I/O beyond EOF"
--msgstr "próbowano wykonać operację we/wy poza końcem pliku"
-+#: .././copy/xfs_copy.c:607
-+#, c-format
-+msgid "%s: couldn't open source \"%s\"\n"
-+msgstr "%s: nie udało się otworzyć źródła \"%s\"\n"
-
--#: .././repair/xfs_repair.c:127
--msgid "inconsistent filesystem geometry in realtime filesystem component"
--msgstr "niespójna geometria systemu plików w składniku realtime"
-+#: .././copy/xfs_copy.c:613
-+#, c-format
-+msgid "%s: couldn't stat source \"%s\"\n"
-+msgstr "%s: nie udało się wykonać stat na źródle \"%s\"\n"
-
--#: .././repair/xfs_repair.c:129
--msgid "maximum indicated percentage of inodes > 100%"
--msgstr "określono maksymalny procent i-węzłów > 100%"
-+#: .././copy/xfs_copy.c:623
-+#, 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"
-
--#: .././repair/xfs_repair.c:131
--msgid "inconsistent inode alignment value"
--msgstr "niespójna wartość wyrównania i-węzła"
-+#: .././copy/xfs_copy.c:628
-+#, c-format
-+msgid "%s: xfsctl on file \"%s\" failed.\n"
-+msgstr "%s: xfsctl na pliku \"%s\" nie powiodło się.\n"
-
--#: .././repair/xfs_repair.c:133
--msgid "not enough secondary superblocks with matching geometry"
--msgstr "za mało zapasowych superbloków o pasującej geometrii"
-+#: .././copy/xfs_copy.c:651
-+#, 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"
-
--#: .././repair/xfs_repair.c:135
--msgid "bad stripe unit in superblock"
--msgstr "błędna jednostka pasa w superbloku"
-+#: .././copy/xfs_copy.c:654
-+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"
-
--#: .././repair/xfs_repair.c:137
--msgid "bad stripe width in superblock"
--msgstr "błędna szerokość pasa w superbloku"
-+#: .././copy/xfs_copy.c:656
-+msgid "\t\tunmounted or mounted read-only. Copy proceeding...\n"
-+msgstr "\t\todmontowane lub podmontowane tylko do odczytu. Kopiowanie w trakcie...\n"
-
--#: .././repair/xfs_repair.c:139
--msgid "bad shared version number in superblock"
--msgstr "błędny numer wersji współdzielenia w superbloku"
-+#: .././copy/xfs_copy.c:673
-+#, 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"
-
--#: .././repair/xfs_repair.c:144
-+#: .././copy/xfs_copy.c:693
- #, c-format
--msgid "bad error code - %d\n"
--msgstr "błędny kod błędu - %d\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"
-
--#: .././repair/xfs_repair.c:152
-+#: .././copy/xfs_copy.c:699
- #, c-format
--msgid "-%c %s option cannot have a value\n"
--msgstr "opcja -%c %s nie przyjmuje wartości\n"
-+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"
-
--#: .././repair/xfs_repair.c:162 .././mkfs/xfs_mkfs.c:2801
-+#: .././copy/xfs_copy.c:703
- #, c-format
--msgid "option respecified\n"
--msgstr "ponownie podana opcja\n"
-+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"
-
--#: .././repair/xfs_repair.c:169 .././mkfs/xfs_mkfs.c:2810
-+#: .././copy/xfs_copy.c:707
- #, c-format
--msgid "unknown option -%c %s\n"
--msgstr "nieznana opcja -%c %s\n"
--
--#: .././repair/xfs_repair.c:248
--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:300
--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"
-+msgid ""
-+"%s: %s has an external log.\n"
-+"%s: Aborting.\n"
-+msgstr ""
-+"%s: %s ma zewnętrzny log.\n"
-+"%s: Przerwano.\n"
-
--#: .././repair/xfs_repair.c:342
-+#: .././copy/xfs_copy.c:711
- #, c-format
- msgid ""
--"\n"
--"fatal error -- "
-+"%s: %s has a real-time section.\n"
-+"%s: Aborting.\n"
- msgstr ""
--"\n"
--"błąd krytyczny - "
-+"%s: %s ma sekcję real-time.\n"
-+"%s: Przerwano.\n"
-
--#: .././repair/xfs_repair.c:454
--#, c-format
--msgid "sb root inode value %<PRIu64> %sinconsistent with calculated value %u\n"
--msgstr "wartość i-węzła głównego superbloku %<PRIu64> %sniespójna z obliczoną wartością %u\n"
-+#: .././copy/xfs_copy.c:736
-+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"
-
--#: .././repair/xfs_repair.c:461
-+#: .././copy/xfs_copy.c:757
- #, 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"
-+msgid "Creating file %s\n"
-+msgstr "Tworzenie pliku %s\n"
-
--#: .././repair/xfs_repair.c:465
-+#: .././copy/xfs_copy.c:775
- #, 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"
-+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"
-
--#: .././repair/xfs_repair.c:477
-+#: .././copy/xfs_copy.c:786
- #, c-format
--msgid "sb realtime bitmap inode %<PRIu64> %sinconsistent with calculated value %u\n"
--msgstr "i-węzeł bitmapy realtime superbloku %<PRIu64> %sniespójny z obliczoną wartością %u\n"
-+msgid "%s: couldn't open target \"%s\"\n"
-+msgstr "%s: nie udało się otworzyć celu \"%s\"\n"
-
--#: .././repair/xfs_repair.c:484
-+#: .././copy/xfs_copy.c:796
- #, 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"
-+msgid "%s: cannot grow data section.\n"
-+msgstr "%s: nie można powiększyć sekcji danych.\n"
-
--#: .././repair/xfs_repair.c:488
-+#: .././copy/xfs_copy.c:804
- #, 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"
-+msgid "%s: xfsctl on \"%s\" failed.\n"
-+msgstr "%s: xfsctl na \"%s\" nie powiodło się.\n"
-
--#: .././repair/xfs_repair.c:500
-+#: .././copy/xfs_copy.c:823
- #, c-format
--msgid "sb realtime summary inode %<PRIu64> %sinconsistent with calculated value %u\n"
--msgstr "i-węzeł opisu realtime superbloku %<PRIu64> %sniespójny z obliczoną wartością %u\n"
-+msgid "%s: failed to write last block\n"
-+msgstr "%s: nie udało się zapisać ostatniego bloku\n"
-
--#: .././repair/xfs_repair.c:507
-+#: .././copy/xfs_copy.c:825
- #, 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"
-+msgid "\tIs target \"%s\" too small?\n"
-+msgstr "\tCzy cel \"%s\" jest zbyt mały?\n"
-
--#: .././repair/xfs_repair.c:511
--#, 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"
-+#: .././copy/xfs_copy.c:835
-+msgid "Couldn't initialize global thread mask\n"
-+msgstr "Nie udało się zainicjować globalnej maski wątków\n"
-
--#: .././repair/xfs_repair.c:554
--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"
-+#: .././copy/xfs_copy.c:842
-+msgid "Error initializing wbuf 0\n"
-+msgstr "Błąd inicjalizacji wbuf 0\n"
-
--#: .././repair/xfs_repair.c:577
--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"
-+#: .././copy/xfs_copy.c:850
-+msgid "Error initializing btree buf 1\n"
-+msgstr "Błąd inicjalizacji btree buf 1\n"
-
--#: .././repair/xfs_repair.c:589
--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"
-+#: .././copy/xfs_copy.c:855
-+msgid "Error creating first semaphore.\n"
-+msgstr "Błąd tworzenia pierwszego semafora.\n"
-
--#: .././repair/xfs_repair.c:599
--#, c-format
--msgid "%s: cannot repair this filesystem. Sorry.\n"
--msgstr "%s: niestety nie można naprawić tego systemu plików.\n"
-+#: .././copy/xfs_copy.c:870
-+msgid "Couldn't malloc space for thread args\n"
-+msgstr "Nie udało się przydzielić miejsca na argumenty wątku\n"
-
--#: .././repair/xfs_repair.c:624
-+#: .././copy/xfs_copy.c:882
- #, c-format
--msgid " - reporting progress in intervals of %s\n"
--msgstr " - informowanie o postępie w odstępach %s\n"
-+msgid "Error creating thread mutex %d\n"
-+msgstr "Błąd podczas tworzenia sekcji krytycznej %d wątku\n"
-
--#: .././repair/xfs_repair.c:671
-+#: .././copy/xfs_copy.c:899
- #, c-format
--msgid " - max_mem = %lu, icount = %<PRIu64>, imem = %<PRIu64>, dblock = %<PRIu64>, dmem = %<PRIu64>\n"
--msgstr " - max_mem = %lu, icount = %<PRIu64>, imem = %<PRIu64>, dblock = %<PRIu64>, dmem = %<PRIu64>\n"
-+msgid "Error creating thread for target %d\n"
-+msgstr "Błąd podczas tworzenia wątku dla celu %d\n"
-
--#: .././repair/xfs_repair.c:684
-+#: .././copy/xfs_copy.c:953
- #, 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"
-+msgid "Error: current level %d >= btree levels %d\n"
-+msgstr "Błąd: bieżący poziom %d >= poziomów b-drzewa %d\n"
-
--#: .././repair/xfs_repair.c:689
-+#: .././copy/xfs_copy.c:972
- #, c-format
-+msgid "Bad btree magic 0x%x\n"
-+msgstr "Niewłaściwa liczba magiczna b-drzewa 0x%x\n"
-+
-+#: .././copy/xfs_copy.c:999
-+msgid "WARNING: source filesystem inconsistent.\n"
-+msgstr "UWAGA: źródłowy system plików niespójny.\n"
-+
-+#: .././copy/xfs_copy.c:1001
-+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 ""
--"Not enough RAM available for repair to enable prefetching.\n"
--"This will be _slow_.\n"
--"You need at least %luMB RAM to run with prefetching enabled.\n"
-+"\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 ""
--"Zbyt mało dostępnej pamięci RAM, żeby naprawiać z włączonym prefetch.\n"
--"To będzie _wolne_.\n"
--"Do włączenia prefetch potrzeba przynajmniej %luMB RAM.\n"
--
--#: .././repair/xfs_repair.c:707
--#, c-format
--msgid " - block cache size set to %d entries\n"
--msgstr " - rozmiar bufora bloku ustawiony na %d wpisów\n"
-+"\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"
-
--#: .././repair/xfs_repair.c:736
--msgid "Found unsupported filesystem features. Exiting now.\n"
--msgstr "Znaleziono nie obsługiwane cechy systemu plików. Zakończono.\n"
-+#: .././db/addr.c:72 .././db/attrset.c:86 .././db/attrset.c:189
-+#: .././db/print.c:74 .././db/type.c:142 .././db/write.c:101
-+msgid "no current type\n"
-+msgstr "brak bieżącego typu\n"
-
--#: .././repair/xfs_repair.c:754
-+#: .././db/addr.c:82
- #, 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:773
--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"
-+msgid "no fields for type %s\n"
-+msgstr "brak pól dla typu %s\n"
-
--#: .././repair/xfs_repair.c:779
--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"
-+#: .././db/addr.c:94
-+msgid "array not allowed for addr command\n"
-+msgstr "tablica nie jest dozwolona dla polecenia addr\n"
-
--#: .././repair/xfs_repair.c:782
--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"
-+#: .././db/addr.c:103
-+#, c-format
-+msgid "no next type for field %s\n"
-+msgstr "brak następnego typu dla pola %s\n"
-
--#: .././repair/xfs_repair.c:787
--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"
-+#: .././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"
-
--#: .././repair/xfs_repair.c:790
--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"
-+#: .././db/agf.c:35 .././db/agfl.c:36 .././db/agi.c:35 .././db/sb.c:42
-+msgid "[agno]"
-+msgstr "[agno]"
-
--#: .././repair/xfs_repair.c:796
--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"
-+#: .././db/agf.c:36
-+msgid "set address to agf header"
-+msgstr "ustawienie adresu na nagłówek agf"
-
--#: .././repair/xfs_repair.c:800
-+#: .././db/agf.c:82
- msgid ""
--"Warning: user quota information would be cleared.\n"
--"User quotas could not be enforced until limit information was recreated.\n"
-+"\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"
<Skipped 23543 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/xfsprogs.git/commitdiff/a7a3a492a383de47624401018ec328f6d31537cd
More information about the pld-cvs-commit
mailing list