]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/log
thirdparty/xfsprogs-dev.git
2 years agopo: Fix invalid .de translation format string
David Seifert [Mon, 26 Jun 2023 09:50:46 +0000 (10:50 +0100)] 
po: Fix invalid .de translation format string

* gettext-0.22 validates format strings now
  https://savannah.gnu.org/bugs/index.php?64332#comment1

Bug: https://bugs.gentoo.org/908864
Signed-off-by: David Seifert <soap@gentoo.org>
Signed-off-by: Sam James <sam@gentoo.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: validate block number being freed before adding to xefi
Dave Chinner [Fri, 16 Jun 2023 01:37:41 +0000 (18:37 -0700)] 
xfs: validate block number being freed before adding to xefi

Source kernel commit: 7dfee17b13e5024c5c0ab1911859ded4182de3e5

Bad things happen in defered extent freeing operations if it is
passed a bad block number in the xefi. This can come from a bogus
agno/agbno pair from deferred agfl freeing, or just a bad fsbno
being passed to __xfs_free_extent_later(). Either way, it's very
difficult to diagnose where a null perag oops in EFI creation
is coming from when the operation that queued the xefi has already
been completed and there's no longer any trace of it around....

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: validity check agbnos on the AGFL
Dave Chinner [Fri, 16 Jun 2023 01:37:35 +0000 (18:37 -0700)] 
xfs: validity check agbnos on the AGFL

Source kernel commit: 3148ebf2c0782340946732bfaf3073d23ac833fa

If the agfl or the indexing in the AGF has been corrupted, getting a
block form the AGFL could return an invalid block number. If this
happens, bad things happen. Check the agbno we pull off the AGFL
and return -EFSCORRUPTED if we find somethign bad.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: fix agf/agfl verification on v4 filesystems
Dave Chinner [Fri, 16 Jun 2023 01:37:30 +0000 (18:37 -0700)] 
xfs: fix agf/agfl verification on v4 filesystems

Source kernel commit: e0a8de7da35e5b22b44fa1013ccc0716e17b0c14

When a v4 filesystem has fl_last - fl_first != fl_count, we do not
not detect the corruption and allow the AGF to be used as it if was
fully valid. On V5 filesystems, we reset the AGFL to empty in these
cases and avoid the corruption at a small cost of leaked blocks.

If we don't catch the corruption on V4 filesystems, bad things
happen later when an allocation attempts to trim the free list
and either double-frees stale entries in the AGFl or tries to free
NULLAGBNO entries.

Either way, this is bad. Prevent this from happening by using the
AGFL_NEED_RESET logic for v4 filesysetms, too.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: fix AGF vs inode cluster buffer deadlock
Dave Chinner [Fri, 16 Jun 2023 01:37:24 +0000 (18:37 -0700)] 
xfs: fix AGF vs inode cluster buffer deadlock

Source kernel commit: 82842fee6e5979ca7e2bf4d839ef890c22ffb7aa

Lock order in XFS is AGI -> AGF, hence for operations involving
inode unlinked list operations we always lock the AGI first. Inode
unlinked list operations operate on the inode cluster buffer,
so the lock order there is AGI -> inode cluster buffer.

For O_TMPFILE operations, this now means the lock order set down in
xfs_rename and xfs_link is AGI -> inode cluster buffer -> AGF as the
unlinked ops are done before the directory modifications that may
allocate space and lock the AGF.

Unfortunately, we also now lock the inode cluster buffer when
logging an inode so that we can attach the inode to the cluster
buffer and pin it in memory. This creates a lock order of AGF ->
inode cluster buffer in directory operations as we have to log the
inode after we've allocated new space for it.

This creates a lock inversion between the AGF and the inode cluster
buffer. Because the inode cluster buffer is shared across multiple
inodes, the inversion is not specific to individual inodes but can
occur when inodes in the same cluster buffer are accessed in
different orders.

To fix this we need move all the inode log item cluster buffer
interactions to the end of the current transaction. Unfortunately,
xfs_trans_log_inode() calls are littered throughout the transactions
with no thought to ordering against other items or locking. This
makes it difficult to do anything that involves changing the call
sites of xfs_trans_log_inode() to change locking orders.

However, we do now have a mechanism that allows is to postpone dirty
item processing to just before we commit the transaction: the
->iop_precommit method. This will be called after all the
modifications are done and high level objects like AGI and AGF
buffers have been locked and modified, thereby providing a mechanism
that guarantees we don't lock the inode cluster buffer before those
high level objects are locked.

This change is largely moving the guts of xfs_trans_log_inode() to
xfs_inode_item_precommit() and providing an extra flag context in
the inode log item to track the dirty state of the inode in the
current transaction. This also means we do a lot less repeated work
in xfs_trans_log_inode() by only doing it once per transaction when
all the work is done.

Fixes: 298f7bec503f ("xfs: pin inode backing buffer to the inode log item")
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: restore allocation trylock iteration
Dave Chinner [Fri, 16 Jun 2023 01:37:18 +0000 (18:37 -0700)] 
xfs: restore allocation trylock iteration

Source kernel commit: 00dcd17cfa7f103f7d640ffd34645a2ddab96330

It was accidentally dropped when refactoring the allocation code,
resulting in the AG iteration always doing blocking AG iteration.
This results in a small performance regression for a specific fsmark
test that runs more user data writer threads than there are AGs.

Reported-by: kernel test robot <oliver.sang@intel.com>
Fixes: 2edf06a50f5b ("xfs: factor xfs_alloc_vextent_this_ag() for _iterate_ags()")
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agolibxfs: port transaction precommit hooks to userspace
Darrick J. Wong [Fri, 16 Jun 2023 01:37:12 +0000 (18:37 -0700)] 
libxfs: port transaction precommit hooks to userspace

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agolibxfs: port list_cmp_func_t to userspace
Darrick J. Wong [Fri, 16 Jun 2023 01:37:07 +0000 (18:37 -0700)] 
libxfs: port list_cmp_func_t to userspace

Synchronize our list_sort ABI to match the kernel's.  This will make it
easier to port the log item precommit sorting code to userspace as-is in
the next patch.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agolibxfs: deferred items should call xfs_perag_intent_{get,put}
Darrick J. Wong [Fri, 16 Jun 2023 01:37:01 +0000 (18:37 -0700)] 
libxfs: deferred items should call xfs_perag_intent_{get,put}

Make the intent item _get_group and _put_group functions call
xfs_perag_intent_{get,put} to match the kernel.  In userspace they're
the same thing so this makes no difference.  However, let's not leave
unnecessary discrepancies.

Fixes: 7cb26322f74 ("xfs: allow queued AG intents to drain before scrubbing")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_db: make the hash command print the dirent hash
Darrick J. Wong [Mon, 5 Jun 2023 15:37:15 +0000 (08:37 -0700)] 
xfs_db: make the hash command print the dirent hash

It turns out that the da and dir2 hashname functions are /not/ the same,
at least not on ascii-ci filesystems.  Enhance this debugger command to
support printing the dir2 hashname.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Andrey Albershteyn <aalbersh@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_db: create dirents and xattrs with colliding names
Darrick J. Wong [Mon, 5 Jun 2023 15:37:09 +0000 (08:37 -0700)] 
xfs_db: create dirents and xattrs with colliding names

Create a new debugger command that will create dirent and xattr names
that induce dahash collisions.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Andrey Albershteyn <aalbersh@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_db: hoist name obfuscation code out of metadump.c
Darrick J. Wong [Thu, 15 Jun 2023 16:12:06 +0000 (09:12 -0700)] 
xfs_db: hoist name obfuscation code out of metadump.c

We want to create a debugger command that will create obfuscated names
for directory and xattr names, so hoist the name obfuscation code into a
separate file.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agomkfs: deprecate the ascii-ci feature
Darrick J. Wong [Mon, 5 Jun 2023 15:36:55 +0000 (08:36 -0700)] 
mkfs: deprecate the ascii-ci feature

Deprecate this feature, since the feature is broken.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agomkfs.xfs.8: warn about the version=ci feature
Darrick J. Wong [Mon, 5 Jun 2023 15:36:49 +0000 (08:36 -0700)] 
mkfs.xfs.8: warn about the version=ci feature

Document the exact byte transformations that happen during directory
name lookup when the version=ci feature is enabled.  Warn that this is
not generally compatible, and that people should not use this feature.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_db: fix metadump name obfuscation for ascii-ci filesystems
Darrick J. Wong [Thu, 15 Jun 2023 16:11:04 +0000 (09:11 -0700)] 
xfs_db: fix metadump name obfuscation for ascii-ci filesystems

Now that we've stabilized the dirent hash function for ascii-ci
filesystems, adapt the metadump name obfuscation code to detect when
it's obfuscating a directory entry name on an ascii-ci filesystem and
spit out names that actually have the same hash.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_db: move obfuscate_name assertion to callers
Darrick J. Wong [Mon, 5 Jun 2023 15:36:38 +0000 (08:36 -0700)] 
xfs_db: move obfuscate_name assertion to callers

Currently, obfuscate_name asserts that the hash of the new name is the
same as the old name.  To enable bug fixes in the next patch, move this
assertion to the callers.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agolibxfs: test the ascii case-insensitive hash
Darrick J. Wong [Mon, 5 Jun 2023 15:36:32 +0000 (08:36 -0700)] 
libxfs: test the ascii case-insensitive hash

Now that we've made kernel and userspace use the same tolower code for
computing directory index hashes, add that to the selftest code.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: set bnobt/cntbt numrecs correctly when formatting new AGs
Darrick J. Wong [Thu, 1 Jun 2023 09:41:10 +0000 (11:41 +0200)] 
xfs: set bnobt/cntbt numrecs correctly when formatting new AGs

Source kernel commit: 8e698ee72c4ecbbf18264568eb310875839fd601

Through generic/300, I discovered that mkfs.xfs creates corrupt
filesystems when given these parameters:

# mkfs.xfs -d size=512M /dev/sda -f -d su=128k,sw=4 --unsupported
Filesystems formatted with --unsupported are not supported!!
meta-data=/dev/sda               isize=512    agcount=8, agsize=16352 blks
=                       sectsz=512   attr=2, projid32bit=1
=                       crc=1        finobt=1, sparse=1, rmapbt=1
=                       reflink=1    bigtime=1 inobtcount=1 nrext64=1
data     =                       bsize=4096   blocks=130816, imaxpct=25
=                       sunit=32     swidth=128 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=8192, version=2
=                       sectsz=512   sunit=32 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
=                       rgcount=0    rgsize=0 blks
Discarding blocks...Done.
# xfs_repair -n /dev/sda
Phase 1 - find and verify superblock...
- reporting progress in intervals of 15 minutes
Phase 2 - using internal log
- zero log...
- 16:30:50: zeroing log - 16320 of 16320 blocks done
- scan filesystem freespace and inode maps...
agf_freeblks 25, counted 0 in ag 4
sb_fdblocks 8823, counted 8798

The root cause of this problem is the numrecs handling in
xfs_freesp_init_recs, which is used to initialize a new AG.  Prior to
calling the function, we set up the new bnobt block with numrecs == 1
and rely on _freesp_init_recs to format that new record.  If the last
record created has a blockcount of zero, then it sets numrecs = 0.

That last bit isn't correct if the AG contains the log, the start of the
log is not immediately after the initial blocks due to stripe alignment,
and the end of the log is perfectly aligned with the end of the AG.  For
this case, we actually formatted a single bnobt record to handle the
free space before the start of the (stripe aligned) log, and incremented
arec to try to format a second record.  That second record turned out to
be unnecessary, so what we really want is to leave numrecs at 1.

The numrecs handling itself is overly complicated because a different
function sets numrecs == 1.  Change the bnobt creation code to start
with numrecs set to zero and only increment it after successfully
formatting a free space extent into the btree block.

Fixes: f327a00745ff ("xfs: account for log space when formatting new AGs")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: don't unconditionally null args->pag in xfs_bmap_btalloc_at_eof
Darrick J. Wong [Thu, 1 Jun 2023 09:40:10 +0000 (11:40 +0200)] 
xfs: don't unconditionally null args->pag in xfs_bmap_btalloc_at_eof

Source kernel commit: b82a5c42a5fa7e79426ed047ced3f8482bb66fbc

xfs/170 on a filesystem with su=128k,sw=4 produces this splat:

BUG: kernel NULL pointer dereference, address: 0000000000000010
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
PGD 0 P4D 0
Oops: 0002 [#1] PREEMPT SMP
CPU: 1 PID: 4022907 Comm: dd Tainted: G        W          6.3.0-xfsx #2 6ebeeffbe9577d32
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20171121_152543-x86-ol7-bu
RIP: 0010:xfs_perag_rele+0x10/0x70 [xfs]
RSP: 0018:ffffc90001e43858 EFLAGS: 00010217
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000100
RDX: ffffffffa054e717 RSI: 0000000000000005 RDI: 0000000000000000
RBP: ffff888194eea000 R08: 0000000000000000 R09: 0000000000000037
R10: ffff888100ac1cb0 R11: 0000000000000018 R12: 0000000000000000
R13: ffffc90001e43a38 R14: ffff888194eea000 R15: ffff888194eea000
FS:  00007f93d1a0e740(0000) GS:ffff88843fc80000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000010 CR3: 000000018a34f000 CR4: 00000000003506e0
Call Trace:
<TASK>
xfs_bmap_btalloc+0x1a7/0x5d0 [xfs f85291d6841cbb3dc740083f1f331c0327394518]
xfs_bmapi_allocate+0xee/0x470 [xfs f85291d6841cbb3dc740083f1f331c0327394518]
xfs_bmapi_write+0x539/0x9e0 [xfs f85291d6841cbb3dc740083f1f331c0327394518]
xfs_iomap_write_direct+0x1bb/0x2b0 [xfs f85291d6841cbb3dc740083f1f331c0327394518]
xfs_direct_write_iomap_begin+0x51c/0x710 [xfs f85291d6841cbb3dc740083f1f331c0327394518]
iomap_iter+0x132/0x2f0
__iomap_dio_rw+0x2f8/0x840
iomap_dio_rw+0xe/0x30
xfs_file_dio_write_aligned+0xad/0x180 [xfs f85291d6841cbb3dc740083f1f331c0327394518]
xfs_file_write_iter+0xfb/0x190 [xfs f85291d6841cbb3dc740083f1f331c0327394518]
vfs_write+0x2eb/0x410
ksys_write+0x65/0xe0
do_syscall_64+0x2b/0x80

This crash occurs under the "out_low_space" label.  We grabbed a perag
reference, passed it via args->pag into xfs_bmap_btalloc_at_eof, and
afterwards args->pag is NULL.  Fix the second function not to clobber
args->pag if the caller had passed one in.

Fixes: 85843327094f ("xfs: factor xfs_bmap_btalloc()")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: fix livelock in delayed allocation at ENOSPC
Dave Chinner [Thu, 1 Jun 2023 09:39:10 +0000 (11:39 +0200)] 
xfs: fix livelock in delayed allocation at ENOSPC

Source kernel commit: 9419092fb2630c30e4ffeb9ef61007ef0c61827a

On a filesystem with a non-zero stripe unit and a large sequential
write, delayed allocation will set a minimum allocation length of
the stripe unit. If allocation fails because there are no extents
long enough for an aligned minlen allocation, it is supposed to
fall back to unaligned allocation which allows single block extents
to be allocated.

When the allocator code was rewritting in the 6.3 cycle, this
fallback was broken - the old code used args->fsbno as the both the
allocation target and the allocation result, the new code passes the
target as a separate parameter. The conversion didn't handle the
aligned->unaligned fallback path correctly - it reset args->fsbno to
the target fsbno on failure which broke allocation failure detection
in the high level code and so it never fell back to unaligned
allocations.

This resulted in a loop in writeback trying to allocate an aligned
block, getting a false positive success, trying to insert the result
in the BMBT. This did nothing because the extent already was in the
BMBT (merge results in an unchanged extent) and so it returned the
prior extent to the conversion code as the current iomap.

Because the iomap returned didn't cover the offset we tried to map,
xfs_convert_blocks() then retries the allocation, which fails in the
same way and now we have a livelock.

Reported-and-tested-by: Brian Foster <bfoster@redhat.com>
Fixes: 85843327094f ("xfs: factor xfs_bmap_btalloc()")
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: _{attr,data}_map_shared should take ILOCK_EXCL until iread_extents is completely...
Darrick J. Wong [Thu, 1 Jun 2023 09:38:10 +0000 (11:38 +0200)] 
xfs: _{attr,data}_map_shared should take ILOCK_EXCL until iread_extents is completely done

Source kernel commit: c95356ca884885db702670e24933ee7f2b9f1754

While fuzzing the data fork extent count on a btree-format directory
with xfs/375, I observed the following (excerpted) splat:

XFS: Assertion failed: xfs_isilocked(ip, XFS_ILOCK_EXCL), file: fs/xfs/libxfs/xfs_bmap.c, line: 1208
------------[ cut here ]------------
WARNING: CPU: 0 PID: 43192 at fs/xfs/xfs_message.c:104 assfail+0x46/0x4a [xfs]
Call Trace:
<TASK>
xfs_iread_extents+0x1af/0x210 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd]
xchk_dir_walk+0xb8/0x190 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd]
xchk_parent_count_parent_dentries+0x41/0x80 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd]
xchk_parent_validate+0x199/0x2e0 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd]
xchk_parent+0xdf/0x130 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd]
xfs_scrub_metadata+0x2b8/0x730 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd]
xfs_scrubv_metadata+0x38b/0x4d0 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd]
xfs_ioc_scrubv_metadata+0x111/0x160 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd]
xfs_file_ioctl+0x367/0xf50 [xfs 09f66509ece4938760fac7de64732a0cbd3e39cd]
__x64_sys_ioctl+0x82/0xa0
do_syscall_64+0x2b/0x80
entry_SYSCALL_64_after_hwframe+0x46/0xb0

The cause of this is a race condition in xfs_ilock_data_map_shared,
which performs an unlocked access to the data fork to guess which lock
mode it needs:

Thread 0                          Thread 1

xfs_need_iread_extents
<observe no iext tree>
xfs_ilock(..., ILOCK_EXCL)
xfs_iread_extents
<observe no iext tree>
<check ILOCK_EXCL>
<load bmbt extents into iext>
<notice iext size doesn't
match nextents>
xfs_need_iread_extents
<observe iext tree>
xfs_ilock(..., ILOCK_SHARED)
<tear down iext tree>
xfs_iunlock(..., ILOCK_EXCL)
xfs_iread_extents
<observe no iext tree>
<check ILOCK_EXCL>
*BOOM*

Fix this race by adding a flag to the xfs_ifork structure to indicate
that we have not yet read in the extent records and changing the
predicate to look at the flag state, not if_height.  The memory barrier
ensures that the flag will not be set until the very end of the
function.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: don't consider future format versions valid
Dave Chinner [Wed, 31 May 2023 09:14:21 +0000 (11:14 +0200)] 
xfs: don't consider future format versions valid

Source kernel commit: aa88019851a85df80cb77f143758b13aee09e3d9

In commit fe08cc504448 we reworked the valid superblock version
checks. If it is a V5 filesystem, it is always valid, then we
checked if the version was less than V4 (reject) and then checked
feature fields in the V4 flags to determine if it was valid.

What we missed was that if the version is not V4 at this point,
we shoudl reject the fs. i.e. the check current treats V6+
filesystems as if it was a v4 filesystem. Fix this.

cc: stable@vger.kernel.org
Fixes: fe08cc504448 ("xfs: open code sb verifier feature checks")
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: stabilize the dirent name transformation function used for ascii-ci dir hash...
Darrick J. Wong [Wed, 31 May 2023 09:13:21 +0000 (11:13 +0200)] 
xfs: stabilize the dirent name transformation function used for ascii-ci dir hash computation

Source kernel commit: a9248538facc3d9e769489e50a544509c2f9cebe

Back in the old days, the "ascii-ci" feature was created to implement
case-insensitive directory entry lookups for latin1-encoded names and
remove the large overhead of Samba's case-insensitive lookup code.  UTF8
names were not allowed, but nobody explicitly wrote in the documentation
that this was only expected to work if the system used latin1 names.
The kernel tolower function was selected to prepare names for hashed
lookups.

There's a major discrepancy in the function that computes directory entry
hashes for filesystems that have ASCII case-insensitive lookups enabled.
The root of this is that the kernel and glibc's tolower implementations
have differing behavior for extended ASCII accented characters.  I wrote
a program to spit out characters for which the tolower() return value is
different from the input:

glibc tolower:
65:A 66:B 67:C 68:D 69:E 70:F 71:G 72:H 73:I 74:J 75:K 76:L 77:M 78:N
79:O 80:P 81:Q 82:R 83:S 84:T 85:U 86:V 87:W 88:X 89:Y 90:Z

kernel tolower:
65:A 66:B 67:C 68:D 69:E 70:F 71:G 72:H 73:I 74:J 75:K 76:L 77:M 78:N
79:O 80:P 81:Q 82:R 83:S 84:T 85:U 86:V 87:W 88:X 89:Y 90:Z 192:À 193:Á
194: 195:à196:Ä 197:Å 198:Æ 199:Ç 200:È 201:É 202:Ê 203:Ë 204:Ì 205:Í
206:Π207:Ï 208:Р209:Ñ 210:Ò 211:Ó 212:Ô 213:Õ 214:Ö 215:× 216:Ø 217:Ù
218:Ú 219:Û 220:Ü 221:Ý 222:Þ

Which means that the kernel and userspace do not agree on the hash value
for a directory filename that contains those higher values.  The hash
values are written into the leaf index block of directories that are
larger than two blocks in size, which means that xfs_repair will flag
these directories as having corrupted hash indexes and rewrite the index
with hash values that the kernel now will not recognize.

Because the ascii-ci feature is not frequently enabled and the kernel
touches filesystems far more frequently than xfs_repair does, fix this
by encoding the kernel's toupper predicate and tolower functions into
libxfs.  Give the new functions less provocative names to make it really
obvious that this is a pre-hash name preparation function, and nothing
else.  This change makes userspace's behavior consistent with the
kernel.

Found by auditing obfuscate_name in xfs_metadump as part of working on
parent pointers, wondering how it could possibly work correctly with ci
filesystems, writing a test tool to create a directory with
hash-colliding names, and watching xfs_repair flag it.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: accumulate iextent records when checking bmap
Darrick J. Wong [Wed, 31 May 2023 09:12:21 +0000 (11:12 +0200)] 
xfs: accumulate iextent records when checking bmap

Source kernel commit: 634d4a79e76691020ba73f50416da37a30779e9e

Currently, the bmap scrubber checks file fork mappings individually.  In
the case that the file uses multiple mappings to a single contiguous
piece of space, the scrubber repeatedly locks the AG to check the
existence of a reverse mapping that overlaps this file mapping.  If the
reverse mapping starts before or ends after the mapping we're checking,
it will also crawl around in the bmbt checking correspondence for
adjacent extents.

This is not very time efficient because it does the crawling while
holding the AGF buffer, and checks the middle mappings multiple times.
Instead, create a custom iextent record iterator function that combines
multiple adjacent allocated mappings into one large incore bmbt record.
This is feasible because the incore bmbt record length is 64-bits wide.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: convert xfs_ialloc_has_inodes_at_extent to return keyfill scan results
Darrick J. Wong [Wed, 31 May 2023 09:11:21 +0000 (11:11 +0200)] 
xfs: convert xfs_ialloc_has_inodes_at_extent to return keyfill scan results

Source kernel commit: efc0845f5d3e253f7f46a60b66a94c3164d76ee3

Convert the xfs_ialloc_has_inodes_at_extent function to return keyfill
scan results because for a given range of inode numbers, we might have
no indexed inodes at all; the entire region might be allocated ondisk
inodes; or there might be a mix of the two.

Unfortunately, sparse inodes adds to the complexity, because each inode
record can have holes, which means that we cannot use the generic btree
_scan_keyfill function because we must look for holes in individual
records to decide the result.  On the plus side, online fsck can now
detect sub-chunk discrepancies in the inobt.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: teach scrub to check for sole ownership of metadata objects
Darrick J. Wong [Wed, 31 May 2023 09:10:21 +0000 (11:10 +0200)] 
xfs: teach scrub to check for sole ownership of metadata objects

Source kernel commit: 69115f775f6e8e972a40aa6aa1523bcb0b252b1c

Strengthen online scrub's checking even further by enabling us to check
that a range of blocks are owned solely by a given owner.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: remove pointless shadow variable from xfs_difree_inobt
Darrick J. Wong [Wed, 31 May 2023 09:09:21 +0000 (11:09 +0200)] 
xfs: remove pointless shadow variable from xfs_difree_inobt

Source kernel commit: cc1207662d1a08e253520654e956f5e699826caa

In xfs_difree_inobt, the pag passed in was previously used to look up
the AGI buffer.  There's no need to extract it again, so remove the
shadow variable and shut up -Wshadow.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: implement masked btree key comparisons for _has_records scans
Darrick J. Wong [Wed, 31 May 2023 09:08:21 +0000 (11:08 +0200)] 
xfs: implement masked btree key comparisons for _has_records scans

Source kernel commit: 4a200a0978288f919aba3f015f374f6ed279e658

For keyspace fullness scans, we want to be able to mask off the parts of
the key that we don't care about.  For most btree types we /do/ want the
full keyspace, but for checking that a given space usage also has a full
complement of rmapbt records (even if different/multiple owners) we need
this masking so that we only track sparseness of rm_startblock, not the
whole keyspace (which is extremely sparse).

Augment the ->diff_two_keys and ->keys_contiguous helpers to take a
third union xfs_btree_key argument, and wire up xfs_rmap_has_records to
pass this through.  This third "mask" argument should contain a nonzero
value in each structure field that should be used in the key comparisons
done during the scan.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: replace xfs_btree_has_record with a general keyspace scanner
Darrick J. Wong [Wed, 31 May 2023 09:07:21 +0000 (11:07 +0200)] 
xfs: replace xfs_btree_has_record with a general keyspace scanner

Source kernel commit: 6abc7aef85b1f42cb39a3149f4ab64ca255e41e6

The current implementation of xfs_btree_has_record returns true if it
finds /any/ record within the given range.  Unfortunately, that's not
sufficient for scrub.  We want to be able to tell if a range of keyspace
for a btree is devoid of records, is totally mapped to records, or is
somewhere in between.  By forcing this to be a boolean, we conflated
sparseness and fullness, which caused scrub to return incorrect results.
Fix the API so that we can tell the caller which of those three is the
current state.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: refactor ->diff_two_keys callsites
Darrick J. Wong [Wed, 31 May 2023 09:06:21 +0000 (11:06 +0200)] 
xfs: refactor ->diff_two_keys callsites

Source kernel commit: bd7e795108ccd8d0f3dc34e16957cbba7e89f342

Create wrapper functions around ->diff_two_keys so that we don't have to
remember what the return values mean, and adjust some of the code
comments to reflect the longtime code behavior.  We're going to
introduce more uses of ->diff_two_keys in the next patch, so reduce the
cognitive load for readers by doing this refactoring now.

Suggested-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: refactor converting btree irec to btree key
Darrick J. Wong [Wed, 31 May 2023 09:05:21 +0000 (11:05 +0200)] 
xfs: refactor converting btree irec to btree key

Source kernel commit: ee5fe8ff6d19b35e7547af789cba877dbf04517b

We keep doing these conversions to support btree queries, so refactor
this into a helper.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: fix rm_offset flag handling in rmap keys
Darrick J. Wong [Wed, 31 May 2023 09:04:21 +0000 (11:04 +0200)] 
xfs: fix rm_offset flag handling in rmap keys

Source kernel commit: 08c987deca56687c0930f308f5148ef1af38dc14

Keys for extent interval records in the reverse mapping btree are
supposed to be computed as follows:

(physical block, owner, fork, is_btree, offset)

This provides users the ability to look up a reverse mapping from a file
block mapping record -- start with the physical block; then if there are
multiple records for the same block, move on to the owner; then the
inode fork type; and so on to the file offset.

Unfortunately, the code that creates rmap lookup keys from rmap records
forgot to mask off the record attribute flags, leading to ondisk keys
that look like this:

(physical block, owner, fork, is_btree, unwritten state, offset)

Fortunately, this has all worked ok for the past six years because the
key comparison functions incorrectly ignore the fork/bmbt/unwritten
information that's encoded in the on-disk offset.  This means that
lookup comparisons are only done with:

(physical block, owner, offset)

Queries can (theoretically) return incorrect results because of this
omission.  On consistent filesystems this isn't an issue because xattr
and bmbt blocks cannot be shared and hence the comparisons succeed
purely on the contents of the rm_startblock field.  For the one case
where we support sharing (written data fork blocks) all flag bits are
zero, so the omission in the comparison has no ill effects.

Unfortunately, this bug prevents scrub from detecting incorrect fork and
bmbt flag bits in the rmap btree, so we really do need to fix the
compare code.  Old filesystems with the unwritten bit erroneously set in
the rmap key struct will work fine on new kernels since we still ignore
the unwritten bit.  New filesystems on older kernels will work fine
since the old kernels never paid attention to the unwritten bit.

A previous version of this patch forgot to keep the (un)written state
flag masked during the comparison and caused a major regression in
5.9.x since unwritten extent conversion can update an rmap record
without requiring key updates.

Note that blocks cannot go directly from data fork to attr fork without
being deallocated and reallocated, nor can they be added to or removed
from a bmbt without a free/alloc cycle, so this should not cause any
regressions.

Found by fuzzing keys[1].attrfork = ones on xfs/371.

Fixes: 4b8ed67794fe ("xfs: add rmap btree operations")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: hoist inode record alignment checks from scrub
Darrick J. Wong [Wed, 31 May 2023 09:03:21 +0000 (11:03 +0200)] 
xfs: hoist inode record alignment checks from scrub

Source kernel commit: de1a9ce225e93b22d189f8ffbce20074bc803121

Move the inobt record alignment checks from xchk_iallocbt_rec into
xfs_inobt_check_irec so that they are applied everywhere.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: hoist rmap record flag checks from scrub
Darrick J. Wong [Wed, 31 May 2023 09:02:21 +0000 (11:02 +0200)] 
xfs: hoist rmap record flag checks from scrub

Source kernel commit: e774b2ea0bb130d00e3cb1c29cd91028d0c0c83d

Move the rmap record flag checks from xchk_rmapbt_rec into
xfs_rmap_check_irec so that they are applied everywhere.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: complain about bad file mapping records in the ondisk bmbt
Darrick J. Wong [Wed, 31 May 2023 09:01:21 +0000 (11:01 +0200)] 
xfs: complain about bad file mapping records in the ondisk bmbt

Source kernel commit: 6a3bd8fcf9afb47c703cb268f30f60aa2e7af86a

Similar to what we've just done for the other btrees, create a function
to log corrupt bmbt records and call it whenever we encounter a bad
record in the ondisk btree.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: hoist rmap record flag checks from scrub
Darrick J. Wong [Wed, 31 May 2023 09:00:21 +0000 (11:00 +0200)] 
xfs: hoist rmap record flag checks from scrub

Source kernel commit: 7d7d6d2fd0444904f12e70d9c930556c4eb44337

Move the rmap record flag checks from xchk_rmapbt_rec into
xfs_rmap_check_irec so that they are applied everywhere.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: complain about bad records in query_range helpers
Darrick J. Wong [Wed, 31 May 2023 08:59:21 +0000 (10:59 +0200)] 
xfs: complain about bad records in query_range helpers

Source kernel commit: ee12eaaa435a7be17152ac50943ee77249de624a

For every btree type except for the bmbt, refactor the code that
complains about bad records into a helper and make the ->query_range
helpers call it so that corruptions found via that avenue are logged.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: standardize ondisk to incore conversion for rmap btrees
Darrick J. Wong [Wed, 31 May 2023 08:58:21 +0000 (10:58 +0200)] 
xfs: standardize ondisk to incore conversion for rmap btrees

Source kernel commit: c4e34172da26cb57f56c471728853d3a428ec832

Create a xfs_rmap_check_irec function to detect corruption in btree
records.  Fix all xfs_rmap_btrec_to_irec callsites to call the new
helper and bubble up corruption reports.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: return a failure address from xfs_rmap_irec_offset_unpack
Darrick J. Wong [Wed, 31 May 2023 08:58:13 +0000 (10:58 +0200)] 
xfs: return a failure address from xfs_rmap_irec_offset_unpack

Source kernel commit: 39ab26d59f039c6190bbaa8118a8f0ffed84492a

Currently, xfs_rmap_irec_offset_unpack returns only 0 or -EFSCORRUPTED.
Change this function to return the code address of a failed conversion
in preparation for the next patch, which standardizes localized record
checking and reporting code.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: standardize ondisk to incore conversion for refcount btrees
Darrick J. Wong [Tue, 30 May 2023 11:14:58 +0000 (13:14 +0200)] 
xfs: standardize ondisk to incore conversion for refcount btrees

Source kernel commit: 2b30cc0bf0589d1ea0506c019b9b81de77535c87

Create a xfs_refcount_check_irec function to detect corruption in btree
records.  Fix all xfs_refcount_btrec_to_irec callsites to call the new
helper and bubble up corruption reports.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: standardize ondisk to incore conversion for inode btrees
Darrick J. Wong [Tue, 30 May 2023 11:13:58 +0000 (13:13 +0200)] 
xfs: standardize ondisk to incore conversion for inode btrees

Source kernel commit: 366a0b8d49c3a7edcb5331f254af195716ba4bdf

Create a xfs_inobt_check_irec function to detect corruption in btree
records.  Fix all xfs_inobt_btrec_to_irec callsites to call the new
helper and bubble up corruption reports.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: standardize ondisk to incore conversion for free space btrees
Darrick J. Wong [Tue, 30 May 2023 11:13:55 +0000 (13:13 +0200)] 
xfs: standardize ondisk to incore conversion for free space btrees

Source kernel commit: 35e3b9a11740b53387e7af151768c13700f80696

Create a xfs_alloc_btrec_to_irec function to convert an ondisk record to
an incore record, and a xfs_alloc_check_irec function to detect
corruption.  Replace all the open-coded logic with calls to the new
helpers and bubble up corruption reports.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: allow queued AG intents to drain before scrubbing
Darrick J. Wong [Tue, 30 May 2023 09:04:51 +0000 (11:04 +0200)] 
xfs: allow queued AG intents to drain before scrubbing

Source kernel commit: d5c88131dbf01a30a222ad82d58e0c21a15f0d8e

When a writer thread executes a chain of log intent items, the AG header
buffer locks will cycle during a transaction roll to get from one intent
item to the next in a chain.  Although scrub takes all AG header buffer
locks, this isn't sufficient to guard against scrub checking an AG while
that writer thread is in the middle of finishing a chain because there's
no higher level locking primitive guarding allocation groups.

When there's a collision, cross-referencing between data structures
(e.g. rmapbt and refcountbt) yields false corruption events; if repair
is running, this results in incorrect repairs, which is catastrophic.

Fix this by adding to the perag structure the count of active intents
and make scrub wait until it has both AG header buffer locks and the
intent counter reaches zero.

One quirk of the drain code is that deferred bmap updates also bump and
drop the intent counter.  A fundamental decision made during the design
phase of the reverse mapping feature is that updates to the rmapbt
records are always made by the same code that updates the primary
metadata.  In other words, callers of bmapi functions expect that the
bmapi functions will queue deferred rmap updates.

Some parts of the reflink code queue deferred refcount (CUI) and bmap
(BUI) updates in the same head transaction, but the deferred work
manager completely finishes the CUI before the BUI work is started.  As
a result, the CUI drops the intent count long before the deferred rmap
(RUI) update even has a chance to bump the intent count.  The only way
to keep the intent count elevated between the CUI and RUI is for the BUI
to bump the counter until the RUI has been created.

A second quirk of the intent drain code is that deferred work items must
increment the intent counter as soon as the work item is added to the
transaction.  When a BUI completes and queues an RUI, the RUI must
increment the counter before the BUI decrements it.  The only way to
accomplish this is to require that the counter be bumped as soon as the
deferred work item is created in memory.

In the next patches we'll improve on this facility, but this patch
provides the basic functionality.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: create traced helper to get extra perag references
Darrick J. Wong [Tue, 30 May 2023 08:48:02 +0000 (10:48 +0200)] 
xfs: create traced helper to get extra perag references

Source kernel commit: 9b2e5a234c89f097ec36f922763dfa1465dc06f8

There are a few places in the XFS codebase where a caller has either an
active or a passive reference to a perag structure and wants to give
a passive reference to some other piece of code.  Btree cursor creation
and inode walks are good examples of this.  Replace the open-coded logic
with a helper to do this.

The new function adds a few safeguards -- it checks that there's at
least one reference to the perag structure passed in, and it records the
refcount bump in the ftrace information.  This makes it much easier to
debug perag refcounting problems.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: give xfs_refcount_intent its own perag reference
Darrick J. Wong [Tue, 30 May 2023 08:44:56 +0000 (10:44 +0200)] 
xfs: give xfs_refcount_intent its own perag reference

Source kernel commit: 00e7b3bac1dc8961bd5aa9d39e79131c6bd81181

Give the xfs_refcount_intent a passive reference to the perag structure
data.  This reference will be used to enable scrub intent draining
functionality in subsequent patches.  Any space being modified by a
refcount intent is already allocated, so we need to be able to operate
even if the AG is being shrunk or offlined.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: give xfs_rmap_intent its own perag reference
Darrick J. Wong [Mon, 29 May 2023 08:49:36 +0000 (10:49 +0200)] 
xfs: give xfs_rmap_intent its own perag reference

Source kernel commit: c13418e8eb375872ad297aeec5fa26277febc155

Give the xfs_rmap_intent a passive reference to the perag structure
data.  This reference will be used to enable scrub intent draining
functionality in subsequent patches.  The space we're (reverse) mapping
is already allocated, so we need to be able to operate even if the AG is
being shrunk or offlined.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: give xfs_extfree_intent its own perag reference
Darrick J. Wong [Fri, 26 May 2023 14:03:29 +0000 (16:03 +0200)] 
xfs: give xfs_extfree_intent its own perag reference

Source kernel commit: f6b384631e1e3482c24e35b53adbd3da50e47e8f

Give the xfs_extfree_intent an passive reference to the perag structure
data.  This reference will be used to enable scrub intent draining
functionality in subsequent patches.  The space being freed must already
be allocated, so we need to able to run even if the AG is being offlined
or shrunk.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: pass per-ag references to xfs_free_extent
Darrick J. Wong [Fri, 26 May 2023 13:38:11 +0000 (15:38 +0200)] 
xfs: pass per-ag references to xfs_free_extent

Source kernel commit: b2ccab3199aa7cea9154d80ea2585312c5f6eba0

Pass a reference to the per-AG structure to xfs_free_extent.  Most
callers already have one, so we can eliminate unnecessary lookups.  The
one exception to this is the EFI code, which the next patch will fix.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: give xfs_bmap_intent its own perag reference
Darrick J. Wong [Fri, 26 May 2023 13:16:03 +0000 (15:16 +0200)] 
xfs: give xfs_bmap_intent its own perag reference

Source kernel commit: 774a99b47b588bf0bd9f65d3b241d5bba0b2fcb0

Give the xfs_bmap_intent an active reference to the perag structure
data.  This reference will be used to enable scrub intent draining
functionality in subsequent patches.  Later, shrink will use these
passive references to know if an AG is quiesced or not.

The reason why we take a passive ref for a file mapping operation is
simple: we're committing to some sort of action involving space in an
AG, so we want to indicate our interest in that AG.  The space is
already allocated, so we need to be able to operate on AGs that are
offline or being shrunk.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agolibxfs: Finish renaming xfs_extent_item variables
Carlos Maiolino [Fri, 26 May 2023 13:13:38 +0000 (15:13 +0200)] 
libxfs: Finish renaming xfs_extent_item variables

Finish renaming xfs_extent_free_item variables to xefi on file
libxfs/defer_item.c, because the maintainer overlooked this file while
pulling changes from kernel commit 578c714b215d474c52949e65a914dae67924f0fe.

Signed-off-by: Carlos Maiolino <cem@kernel.org>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
2 years agoxfsprogs: Release v6.3.0 v6.3.0
Carlos Maiolino [Mon, 22 May 2023 09:50:36 +0000 (11:50 +0200)] 
xfsprogs: Release v6.3.0

Update all the necessary files for a 6.3.0 release.

Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_repair: dont leak buffer when discarding directories
Darrick J. Wong [Wed, 3 May 2023 15:15:15 +0000 (08:15 -0700)] 
xfs_repair: dont leak buffer when discarding directories

Commit 1f7c7553489c tried to reduce the memory requirements of phase 6
of repair by redesigning longform_dir2_entry_check without the bplist
array.  Unfortunately, none of us noticed that the code that rejects a
dir block with a bad header now leaks the xfs_buf object because we no
longer have a bplist to drop the buffer references.  Any time we hold a
buffer and decide to move on in the dabno loop, we must release the
buffer.

The immediate result of this error is that dir_binval complains about
the recursive lock count of the buffer when we blow out the directory.
However, if the block is reallocated by another thread, repair will
deadlock when it tries to get the buffer and cannot take the buffer
lock.

Found via xfs/113 fuzzing data format directory blocks.  For whatever
reason this happens much more frequently when su=128k,sw=4, but this
applies to everyone equally.

While we're at it, make the relse at the bottom of the function run for
any remaining buffer reference, even if this isn't a block format
directory to avoid leaving a landmine in case we ever add a "goto
fix" inside the loop for a non-block directory.

Fixes: 1f7c7553489 ("repair: don't duplicate names in phase 6")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_repair: estimate per-AG btree slack better
Darrick J. Wong [Thu, 27 Apr 2023 22:45:21 +0000 (15:45 -0700)] 
xfs_repair: estimate per-AG btree slack better

The slack calculation for per-AG btrees is a bit inaccurate because it
only disables slack space in the new btrees when the amount of free
space in the AG (not counting the btrees) is less than 3/32ths of the
AG.  In other words, it assumes that the btrees will fit in less than 9
percent of the space.

However, there's one scenario where this goes wrong -- if the rmapbt
consumes a significant portion of the AG space.  Say a filesystem is
hosting a VM image farm that starts with perfectly shared images.  As
time goes by, random writes to those images will slowly cause the rmapbt
to increase in size as blocks within those images get COWed.

Suppose that the rmapbt now consumes 20% of the space in the AG, that
the AG is nearly full, and that the blocks in the old rmapbt are mostly
full.  At the start of phase5_func, mk_incore_fstree will return that
num_freeblocks is ~20% of the AG size.  Hence the slack calculation will
conclude that there's plenty of space in the AG and new btrees will be
built with 25% slack in the blocks.  If the size of these new expanded
btrees is larger than the free space in the AG, repair will fail to
allocate btree blocks and fail, causing severe filesystem damage.

To combat this, estimate the worst case size of the AG btrees given the
number of records we intend to put in them, subtract that worst case
figure from num_freeblocks, and feed that to bulkload_estimate_ag_slack.
This results in tighter packing of new btree blocks when space is dear,
and hopefully fewer problems.  This /can/ be reproduced with generic/333
if you hack it to keep COWing blocks until the filesystem is totally
out of space, even if reflink has long since refused to share more
blocks.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agomkfs: warning about misaligned AGs and RAID stripes is not an error
Darrick J. Wong [Wed, 10 May 2023 13:15:15 +0000 (15:15 +0200)] 
mkfs: warning about misaligned AGs and RAID stripes is not an error

I've noticed a fair number of fstests failures when we create a scratch
device on a RAID device and the test specifies an explicit AG count or
AG size:

--- /tmp/fstests/tests/xfs/042.out 2022-09-01 15:09:11.484679979 -0700
+++ /var/tmp/fstests/xfs/042.out.bad 2023-04-25 19:59:04.040000000 -0700
@@ -1,5 +1,8 @@
 QA output created by 042
-Make a 96 megabyte filesystem on SCRATCH_DEV and mount... done
+Make a 96 megabyte filesystem on SCRATCH_DEV and mount... Warning: AG size is a multiple of stripe width.  This can cause performance
+problems by aligning all AGs on the same disk.  To avoid this, run mkfs with
+an AG size that is one stripe unit smaller or larger, for example 8160.
+done

Emitting this warning on stderr is silly -- nothing has failed, and we
aren't going to abort the format either.  Send the warning to stdout.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_db: fix broken logic in error path
Darrick J. Wong [Thu, 27 Apr 2023 19:02:33 +0000 (12:02 -0700)] 
xfs_db: fix broken logic in error path

smatch complains proceeding into the if body if leaf is a null pointer:

check.c:3614 process_leaf_node_dir_v2_int() warn: variable dereferenced before check 'leaf' (see line 3518)

However, the logic here is misleading and broken -- what we're trying to
do is switch between the v4 and v5 variants of the directory check.
We're using @leaf3 being a null pointer (or not) to determine v4 vs. v5,
so the "!" part of the comparison is correct, but the variable used
(leaf) is not.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: fix mismerged tracepoints
Darrick J. Wong [Tue, 9 May 2023 09:34:40 +0000 (11:34 +0200)] 
xfs: fix mismerged tracepoints

Source kernel commit: 4dfb02d5cae80289384c4d3c6ddfbd92d30aced9

At some point in between sending this patch to the list and merging it
into for-next, the tracepoints got all mixed up because I've
over-reliant on automated tools not sucking.  The end result is that the
tracepoints are all wrong, so fix them.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: clear incore AGFL_RESET state if it's not needed
Darrick J. Wong [Tue, 9 May 2023 09:33:43 +0000 (11:33 +0200)] 
xfs: clear incore AGFL_RESET state if it's not needed

Source kernel commit: e2e63b071b2da53ad6a154e34c387bb064137f74

Prior to commit 7ac2ff8bb371, when we loaded the incore perag structure
with information from the AGF header, we would set or clear the
pagf_agfl_reset field based on whether or not the AGFL list was
misaligned within the block.  IOWs, it's an incore state bit that's
supposed to cache something in the ondisk metadata.  Therefore, the code
still needs to support clearing the incore bit if (somehow) the AGFL
were to correct itself.

It turns out that xfs_repair does exactly this -- phase 4 loads the AGF
to scan the rmapbt for corrupt records, which can set NEEDS_AGFL_RESET.
The scan unsets AGF_INIT but doesn't unset NEEDS_AGFL_RESET.  Phase 5
totally rewrites the AGFL and fixes the alignment problem, didn't clear
NEEDS_AGFL_RESET historically, and reloads the perag state to fix the
freelist.  This results in the AGFL being reset based on stale data,
which then causes the new AGFL blocks to be leaked.  A subsequent
xfs_repair -n then complains about the leaks.

One could argue that phase 5 ought to clear this bit directly when it
reloads the perag AGF data after rewriting the AGFL, but libxfs used to
handle this for us, so it should go back to doing that.

Found by fuzzing flfirst = ones in xfs/352.

Fixes: 7ac2ff8bb371 ("xfs: perags need atomic operational state")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: add tracepoints for each of the externally visible allocators
Darrick J. Wong [Tue, 9 May 2023 09:32:43 +0000 (11:32 +0200)] 
xfs: add tracepoints for each of the externally visible allocators

Source kernel commit: e6fbb7167ed005783ac5aef3e75699f45ffe2af8

There are now five separate space allocator interfaces exposed to the
rest of XFS for five different strategies to find space.  Add
tracepoints for each of them so that I can tell from a trace dump
exactly which ones got called and what happened underneath them.  Add a
sixth so it's more obvious if an allocation actually happened.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: walk all AGs if TRYLOCK passed to xfs_alloc_vextent_iterate_ags
Darrick J. Wong [Tue, 9 May 2023 09:30:52 +0000 (11:30 +0200)] 
xfs: walk all AGs if TRYLOCK passed to xfs_alloc_vextent_iterate_ags

Source kernel commit: 9eb775968b68d049fb3b00353f12cd10308527c7

Callers of xfs_alloc_vextent_iterate_ags that pass in the TRYLOCK flag
want us to perform a non-blocking scan of the AGs for free space.  There
are no ordering constraints for non-blocking AGF lock acquisition, so
the scan can freely start over at AG 0 even when minimum_agno > 0.

This manifests fairly reliably on xfs/294 on 6.3-rc2 with the parent
pointer patchset applied and the realtime volume enabled.  I observed
the following sequence as part of an xfs_dir_createname call:

0. Fragment the free space, then allocate nearly all the free space in
all AGs except AG 0.

1. Create a directory in AG 2 and let it grow for a while.

2. Try to allocate 2 blocks to expand the dirent part of a directory.
The space will be allocated out of AG 0, but the allocation will not
be contiguous.  This (I think) activates the LOWMODE allocator.

3. The bmapi call decides to convert from extents to bmbt format and
tries to allocate 1 block.  This allocation request calls
xfs_alloc_vextent_start_ag with the inode number, which starts the
scan at AG 2.  We ignore AG 0 (with all its free space) and instead
scrape AG 2 and 3 for more space.  We find one block, but this now
kicks t_highest_agno to 3.

4. The createname call decides it needs to split the dabtree.  It tries
to allocate even more space with xfs_alloc_vextent_start_ag, but now
we're constrained to AG 3, and we don't find the space.  The
createname returns ENOSPC and the filesystem shuts down.

This change fixes the problem by making the trylock scan wrap around to
AG 0 if it doesn't like the AGs that it finds.  Since the current
transaction itself holds AGF 0, the trylock of AGF 0 will succeed, and
we take space from the AG that has plenty.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: try to idiot-proof the allocators
Darrick J. Wong [Tue, 9 May 2023 09:30:49 +0000 (11:30 +0200)] 
xfs: try to idiot-proof the allocators

Source kernel commit: 6de4b1ab470fe52351415217ac6dffddee571c45

In porting his development branch to 6.3-rc1, yours truly has
repeatedly screwed up the args->pag being fed to the xfs_alloc_vextent*
functions.  Add some debugging assertions to test the preconditions
required of the callers.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: restore old agirotor behavior
Darrick J. Wong [Tue, 9 May 2023 09:30:48 +0000 (11:30 +0200)] 
xfs: restore old agirotor behavior

Source kernel commit: 6e2985c938e8b765b3de299c561d87f98330c546

Prior to the removal of xfs_ialloc_next_ag, we would increment the agi
rotor and return the *old* value.  atomic_inc_return returns the new
value, which causes mkfs to allocate the root directory in AG 1.  Put
back the old behavior (at least for mkfs) by subtracting 1 here.

Fixes: 20a5eab49d35 ("xfs: convert xfs_ialloc_next_ag() to an atomic")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: return a referenced perag from filestreams allocator
Dave Chinner [Tue, 9 May 2023 09:30:46 +0000 (11:30 +0200)] 
xfs: return a referenced perag from filestreams allocator

Source kernel commit: f8f1ed1ab3babad46b25e2dbe8de43b33fe7aaa6

Now that the filestreams AG selection tracks active perags, we need
to return an active perag to the core allocator code. This is
because the file allocation the filestreams code will run are AG
specific allocations and so need to pin the AG until the allocations
complete.

We cannot rely on the filestreams item reference to do this - the
filestreams association can be torn down at any time, hence we
need to have a separate reference for the allocation process to pin
the AG after it has been selected.

This means there is some perag juggling in allocation failure
fallback paths as they will do all AG scans in the case the AG
specific allocation fails. Hence we need to track the perag
reference that the filestream allocator returned to make sure we
don't leak it on repeated allocation failure.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: move xfs_bmap_btalloc_filestreams() to xfs_filestreams.c
Dave Chinner [Tue, 9 May 2023 09:30:44 +0000 (11:30 +0200)] 
xfs: move xfs_bmap_btalloc_filestreams() to xfs_filestreams.c

Source kernel commit: 8f7747ad8c52cde585b9456f6dbd1984af7b97bc

xfs_bmap_btalloc_filestreams() calls two filestreams functions to
select the AG to allocate from. Both those functions end up in
the same selection function that iterates all AGs multiple times.
Worst case, xfs_bmap_btalloc_filestreams() can iterate all AGs 4
times just to select the initial AG to allocate in.

Move the AG selection to fs/xfs/xfs_filestreams.c as a single
interface so that the inefficient AG interation is contained
entirely within the filestreams code. This will allow the
implementation to be simplified and made more efficient in future
patches.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: use xfs_bmap_longest_free_extent() in filestreams
Dave Chinner [Tue, 9 May 2023 09:30:43 +0000 (11:30 +0200)] 
xfs: use xfs_bmap_longest_free_extent() in filestreams

Source kernel commit: 05cf492a8d01f48d4b8d8f0b93f2d75de7349f12

The code in xfs_bmap_longest_free_extent() is open coded in
xfs_filestream_pick_ag(). Export xfs_bmap_longest_free_extent and
call it from the filestreams code instead.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: get rid of notinit from xfs_bmap_longest_free_extent
Dave Chinner [Tue, 9 May 2023 09:30:41 +0000 (11:30 +0200)] 
xfs: get rid of notinit from xfs_bmap_longest_free_extent

Source kernel commit: 6b637ad0c7be85ecb795697ea51051039b753da2

It is only set if reading the AGF gets a EAGAIN error. Just return
the EAGAIN error and handle that error in the callers.

This means we can remove the not_init parameter from
xfs_bmap_select_minlen(), too, because the use of not_init there is
pessimistic. If we can't read the agf, it won't increase blen.

The only time we actually care whether we checked all the AGFs for
contiguous free space is when the best length is less than the
minimum allocation length. If not_init is set, then we ignore blen
and set the minimum alloc length to the absolute minimum, not the
best length we know already is present.

However, if blen is less than the minimum we're going to ignore it
anyway, regardless of whether we scanned all the AGFs or not.  Hence
not_init can go away, because we only use if blen is good from
the scanned AGs otherwise we ignore it altogether and use minlen.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: factor out filestreams from xfs_bmap_btalloc_nullfb
Dave Chinner [Tue, 9 May 2023 09:30:39 +0000 (11:30 +0200)] 
xfs: factor out filestreams from xfs_bmap_btalloc_nullfb

Source kernel commit: 89563e7dc099343bf7792515452e1a24005d98a6

There's many if (filestreams) {} else {} branches in this function.
Split it out into a filestreams specific function so that we can
then work directly on cleaning up the filestreams code without
impacting the rest of the allocation algorithms.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: convert xfs_alloc_vextent_iterate_ags() to use perag walker
Dave Chinner [Tue, 9 May 2023 09:30:33 +0000 (11:30 +0200)] 
xfs: convert xfs_alloc_vextent_iterate_ags() to use perag walker

Source kernel commit: 3432ef6111997f39d2f708dd508159dfaca72942

Now that the AG iteration code in the core allocation code has been
cleaned up, we can easily convert it to use a for_each_perag..()
variant to use active references and skip AGs that it can't get
active references on.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: move the minimum agno checks into xfs_alloc_vextent_check_args
Dave Chinner [Tue, 9 May 2023 09:30:32 +0000 (11:30 +0200)] 
xfs: move the minimum agno checks into xfs_alloc_vextent_check_args

Source kernel commit: 8b81356825ffb96b3b167b4dabbbbdb506bb0e0b

All of the allocation functions now extract the minimum allowed AG
from the transaction and then use it in some way. The allocation
functions that are restricted to a single AG all check if the
AG requested can be allocated from and return an error if so. These
all set args->agno appropriately.

All the allocation functions that iterate AGs use it to calculate
the scan start AG. args->agno is not set until the iterator starts
walking AGs.

Hence we can easily set up a conditional check against the minimum
AG allowed in xfs_alloc_vextent_check_args() based on whether
args->agno contains NULLAGNUMBER or not and move all the repeated
setup code to xfs_alloc_vextent_check_args(), further simplifying
the allocation functions.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: fold xfs_alloc_ag_vextent() into callers
Dave Chinner [Tue, 9 May 2023 09:30:30 +0000 (11:30 +0200)] 
xfs: fold xfs_alloc_ag_vextent() into callers

Source kernel commit: 230e8fe8462ffda0849ea40b61dcf9f233854076

We don't need the multiplexing xfs_alloc_ag_vextent() provided
anymore - we can just call the exact/near/size variants directly.
This allows us to remove args->type completely and stop using
args->fsbno as an input to the allocator algorithms.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: move allocation accounting to xfs_alloc_vextent_set_fsbno()
Dave Chinner [Tue, 9 May 2023 09:30:29 +0000 (11:30 +0200)] 
xfs: move allocation accounting to xfs_alloc_vextent_set_fsbno()

Source kernel commit: e4d174260779ff0e2dc5de951c2e235721b02b05

Move it from xfs_alloc_ag_vextent() so we can get rid of that layer.
Rename xfs_alloc_vextent_set_fsbno() to xfs_alloc_vextent_finish()
to indicate that it's function is finishing off the allocation that
we've run now that it contains much more functionality.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: introduce xfs_alloc_vextent_prepare()
Dave Chinner [Tue, 9 May 2023 09:30:28 +0000 (11:30 +0200)] 
xfs: introduce xfs_alloc_vextent_prepare()

Source kernel commit: 74b9aa63193b288191d6f01b61c819cef2807138

Now that we have wrapper functions for each type of allocation we
can ask for, we can start unravelling xfs_alloc_ag_vextent(). That
is essentially just a prepare stage, the allocation multiplexer
and a post-allocation accounting step is the allocation proceeded.

The current xfs_alloc_vextent*() wrappers all have a prepare stage,
the allocation operation and a post-allocation accounting step.

We can consolidate this by moving the AG alloc prep code into the
wrapper functions, the accounting code in the wrapper accounting
functions, and cut out the multiplexer layer entirely.

This patch consolidates the AG preparation stage.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: introduce xfs_alloc_vextent_exact_bno()
Dave Chinner [Tue, 9 May 2023 09:30:26 +0000 (11:30 +0200)] 
xfs: introduce xfs_alloc_vextent_exact_bno()

Source kernel commit: 5f36b2ce79f254dd00cdc88374271df7ce843d56

Two of the callers to xfs_alloc_vextent_this_ag() actually want
exact block number allocation, not anywhere-in-ag allocation. Split
this out from _this_ag() as a first class citizen so no external
extent allocation code needs to care about args->type anymore.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: introduce xfs_alloc_vextent_near_bno()
Dave Chinner [Tue, 9 May 2023 09:30:25 +0000 (11:30 +0200)] 
xfs: introduce xfs_alloc_vextent_near_bno()

Source kernel commit: db4710fd12248e5d4c3842520cd13f034136576b

The remaining callers of xfs_alloc_vextent() are all doing NEAR_BNO
allocations. We can replace that function with a new
xfs_alloc_vextent_near_bno() function that does this explicitly.

We also multiplex NEAR_BNO allocations through
xfs_alloc_vextent_this_ag via args->type. Replace all of these with
direct calls to xfs_alloc_vextent_near_bno(), too.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: use xfs_alloc_vextent_start_bno() where appropriate
Dave Chinner [Tue, 9 May 2023 09:30:24 +0000 (11:30 +0200)] 
xfs: use xfs_alloc_vextent_start_bno() where appropriate

Source kernel commit: 2a7f6d41d8b72412228ede538bdf0e81bf9738f4

Change obvious callers of single AG allocation to use
xfs_alloc_vextent_start_bno(). Callers no long need to specify
XFS_ALLOCTYPE_START_BNO, and so the type can be driven inward and
removed.

While doing this, also pass the allocation target fsb as a parameter
rather than encoding it in args->fsbno.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: use xfs_alloc_vextent_first_ag() where appropriate
Dave Chinner [Tue, 9 May 2023 09:30:23 +0000 (11:30 +0200)] 
xfs: use xfs_alloc_vextent_first_ag() where appropriate

Source kernel commit: 319c9e874ac8721acdb6583e3459ef595e5ed0a6

Change obvious callers of single AG allocation to use
xfs_alloc_vextent_first_ag(). This gets rid of
XFS_ALLOCTYPE_FIRST_AG as the type used within
xfs_alloc_vextent_first_ag() during iteration is _THIS_AG. Hence we
can remove the setting of args->type from all the callers of
_first_ag() and remove the alloctype.

While doing this, pass the allocation target fsb as a parameter
rather than encoding it in args->fsbno. This starts the process
of making args->fsbno an output only variable rather than
input/output.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: factor xfs_bmap_btalloc()
Dave Chinner [Tue, 9 May 2023 09:29:59 +0000 (11:29 +0200)] 
xfs: factor xfs_bmap_btalloc()

Source kernel commit: 85843327094f9de9cf0129cd9a3a43128c6f5ac8

There are several different contexts xfs_bmap_btalloc() handles, and
large chunks of the code execute independent allocation contexts.
Try to untangle this mess a bit.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: use xfs_alloc_vextent_this_ag() where appropriate
Dave Chinner [Tue, 9 May 2023 09:29:57 +0000 (11:29 +0200)] 
xfs: use xfs_alloc_vextent_this_ag() where appropriate

Source kernel commit: 74c36a8689d3d8ca9d9e96759c9bbf337e049097

Change obvious callers of single AG allocation to use
xfs_alloc_vextent_this_ag(). Drive the per-ag grabbing out to the
callers, too, so that callers with active references don't need
to do new lookups just for an allocation in a context that already
has a perag reference.

The only remaining caller that does single AG allocation through
xfs_alloc_vextent() is xfs_bmap_btalloc() with
XFS_ALLOCTYPE_NEAR_BNO. That is going to need more untangling before
it can be converted cleanly.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: combine __xfs_alloc_vextent_this_ag and xfs_alloc_ag_vextent
Dave Chinner [Tue, 9 May 2023 09:29:54 +0000 (11:29 +0200)] 
xfs: combine __xfs_alloc_vextent_this_ag and  xfs_alloc_ag_vextent

Source kernel commit: 4811c933ea1ab7de86507dc9f7c9d3d9d71cafb5

There's a bit of a recursive conundrum around
xfs_alloc_ag_vextent(). We can't first call xfs_alloc_ag_vextent()
without preparing the AGFL for the allocation, and preparing the
AGFL calls xfs_alloc_ag_vextent() to prepare the AGFL for the
allocation. This "double allocation" requirement is not really clear
from the current xfs_alloc_fix_freelist() calls that are sprinkled
through the allocation code.

It's not helped that xfs_alloc_ag_vextent() can actually allocate
from the AGFL itself, but there's special code to prevent AGFL prep
allocations from allocating from the free list it's trying to prep.
The naming is also not consistent: args->wasfromfl is true when we
allocated _from_ the free list, but the indication that we are
allocating _for_ the free list is via checking that (args->resv ==
XFS_AG_RESV_AGFL).

So, lets make this "allocation required for allocation" situation
clear by moving it all inside xfs_alloc_ag_vextent(). The freelist
allocation is a specific XFS_ALLOCTYPE_THIS_AG allocation, which
translated directly to xfs_alloc_ag_vextent_size() allocation.

This enables us to replace __xfs_alloc_vextent_this_ag() with a call
to xfs_alloc_ag_vextent(), and we drive the freelist fixing further
into the per-ag allocation algorithm.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: factor xfs_alloc_vextent_this_ag() for _iterate_ags()
Dave Chinner [Tue, 9 May 2023 09:29:52 +0000 (11:29 +0200)] 
xfs: factor xfs_alloc_vextent_this_ag() for  _iterate_ags()

Source kernel commit: 2edf06a50f5bbe664283f3c55c480fc013221d70

The core of the per-ag iteration is effectively doing a "this ag"
allocation on one AG at a time. Use the same code to implement the
core "this ag" allocation in both xfs_alloc_vextent_this_ag()
and xfs_alloc_vextent_iterate_ags().

This means we only call xfs_alloc_ag_vextent() from one place so we
can easily collapse the call stack in future patches.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: rework xfs_alloc_vextent()
Dave Chinner [Tue, 9 May 2023 09:29:51 +0000 (11:29 +0200)] 
xfs: rework xfs_alloc_vextent()

Source kernel commit: ecd788a92460eef44c5444290757bfd0f38d91b4

It's a multiplexing mess that can be greatly simplified, and really
needs to be simplified to allow active per-ag references to
propagate from initial AG selection code the the bmapi code.

This splits the code out into separate a parameter checking
function, an iterator function, and allocation completion functions
and then implements the individual policies using these functions.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: introduce xfs_for_each_perag_wrap()
Dave Chinner [Tue, 9 May 2023 09:29:50 +0000 (11:29 +0200)] 
xfs: introduce xfs_for_each_perag_wrap()

Source kernel commit: 76257a15873ccce817e0c4441f6bb66fb8f8201c

In several places we iterate every AG from a specific start agno and
wrap back to the first AG when we reach the end of the filesystem to
continue searching. We don't have a primitive for this iteration
yet, so add one for conversion of these algorithms to per-ag based
iteration.

The filestream AG select code is a mess, and this initially makes it
worse. The per-ag selection needs to be driven completely into the
filestream code to clean this up and it will be done in a future
patch that makes the filestream allocator use active per-ag
references correctly.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: perags need atomic operational state
Dave Chinner [Tue, 9 May 2023 09:29:49 +0000 (11:29 +0200)] 
xfs: perags need atomic operational state

Source kernel commit: 7ac2ff8bb3713c7cb43564c04384af2ee7cc1f8d

We currently don't have any flags or operational state in the
xfs_perag except for the pagf_init and pagi_init flags. And the
agflreset flag. Oh, there's also the pagf_metadata and pagi_inodeok
flags, too.

For controlling per-ag operations, we are going to need some atomic
state flags. Hence add an opstate field similar to what we already
have in the mount and log, and convert all these state flags across
to atomic bit operations.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: convert xfs_ialloc_next_ag() to an atomic
Dave Chinner [Tue, 9 May 2023 09:29:48 +0000 (11:29 +0200)] 
xfs: convert xfs_ialloc_next_ag() to an atomic

Source kernel commit: 20a5eab49d354a2837e0af3f07f92a104de52804

This is currently a spinlock lock protected rotor which can be
implemented with a single atomic operation. Change it to be more
efficient and get rid of the m_agirotor_lock. Noticed while
converting the inode allocation AG selection loop to active perag
references.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: inobt can use perags in many more places than it does
Dave Chinner [Tue, 9 May 2023 09:29:47 +0000 (11:29 +0200)] 
xfs: inobt can use perags in many more places than it does

Source kernel commit: bab8b795185bf37801a4f7ee5c321eee288c2f10

Lots of code in the inobt infrastructure is passed both xfs_mount
and perags. We only need perags for the per-ag inode allocation
code, so reduce the duplication by passing only the perags as the
primary object.

This ends up reducing the code size by a bit:

text    data     bss     dec     hex filename
orig    1138878  323979     548 1463405  16546d (TOTALS)
patched 1138709  323979     548 1463236  1653c4 (TOTALS)

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: use active perag references for inode allocation
Dave Chinner [Tue, 9 May 2023 09:29:44 +0000 (11:29 +0200)] 
xfs: use active perag references for inode allocation

Source kernel commit: dedab3e4379d298ed60b6c52a15168807b48d57a

Convert the inode allocation routines to use active perag references
or references held by callers rather than grab their own. Also drive
the perag further inwards to replace xfs_mounts when doing
operations on a specific AG.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: convert xfs_imap() to take a perag
Dave Chinner [Tue, 9 May 2023 09:29:43 +0000 (11:29 +0200)] 
xfs: convert xfs_imap() to take a perag

Source kernel commit: 498f0adbcdb6a68403bfb9645a7555b789a7fee4

Callers have referenced perags but they don't pass it into
xfs_imap() so it takes it's own reference. Fix that so we can change
inode allocation over to using active references.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: rework the perag trace points to be perag centric
Dave Chinner [Tue, 9 May 2023 09:29:42 +0000 (11:29 +0200)] 
xfs: rework the perag trace points to be perag centric

Source kernel commit: 368e2d09b41caa5b44a61bb518c362f46d6d615c

So that they all output the same information in the traces to make
debugging refcount issues easier.

This means that all the lookup/drop functions no longer need to use
the full memory barrier atomic operations (atomic*_return()) so
will have less overhead when tracing is off. The set/clear tag
tracepoints no longer abuse the reference count to pass the tag -
the tag being cleared is obvious from the _RET_IP_ that is recorded
in the trace point.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: active perag reference counting
Dave Chinner [Tue, 9 May 2023 09:29:41 +0000 (11:29 +0200)] 
xfs: active perag reference counting

Source kernel commit: c4d5660afbdcd3f0fa3bbf563e059511fba8445f

We need to be able to dynamically remove instantiated AGs from
memory safely, either for shrinking the filesystem or paging AG
state in and out of memory (e.g. supporting millions of AGs). This
means we need to be able to safely exclude operations from accessing
perags while dynamic removal is in progress.

To do this, introduce the concept of active and passive references.
Active references are required for high level operations that make
use of an AG for a given operation (e.g. allocation) and pin the
perag in memory for the duration of the operation that is operating
on the perag (e.g. transaction scope). This means we can fail to get
an active reference to an AG, hence callers of the new active
reference API must be able to handle lookup failure gracefully.

Passive references are used in low level code, where we might need
to access the perag structure for the purposes of completing high
level operations. For example, buffers need to use passive
references because:
- we need to be able to do metadata IO during operations like grow
and shrink transactions where high level active references to the
AG have already been blocked
- buffers need to pin the perag until they are reclaimed from
memory, something that high level code has no direct control over.
- unused cached buffers should not prevent a shrink from being
started.

Hence we have active references that will form exclusion barriers
for operations to be performed on an AG, and passive references that
will prevent reclaim of the perag until all objects with passive
references have been reclaimed themselves.

This patch introduce xfs_perag_grab()/xfs_perag_rele() as the API
for active AG reference functionality. We also need to convert the
for_each_perag*() iterators to use active references, which will
start the process of converting high level code over to using active
references. Conversion of non-iterator based code to active
references will be done in followup patches.

Note that the implementation using reference counting is really just
a development vehicle for the API to ensure we don't have any leaks
in the callers. Once we need to remove perag structures from memory
dyanmically, we will need a much more robust per-ag state transition
mechanism for preventing new references from being taken while we
wait for existing references to drain before removal from memory can
occur....

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: t_firstblock is tracking AGs not blocks
Dave Chinner [Tue, 9 May 2023 09:29:40 +0000 (11:29 +0200)] 
xfs: t_firstblock is tracking AGs not blocks

Source kernel commit: 692b6cddeb65a5170c1e63d25b1ffb7822e80f7d

The tp->t_firstblock field is now raelly tracking the highest AG we
have locked, not the block number of the highest allocation we've
made. It's purpose is to prevent AGF locking deadlocks, so rename it
to "highest AG" and simplify the implementation to just track the
agno rather than a fsbno.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: drop firstblock constraints from allocation setup
Dave Chinner [Tue, 9 May 2023 09:29:39 +0000 (11:29 +0200)] 
xfs: drop firstblock constraints from allocation setup

Source kernel commit: 36b6ad2d9cb81b0d52ae1598286ca5809cd39003

Now that xfs_alloc_vextent() does all the AGF deadlock prevention
filtering for multiple allocations in a single transaction, we no
longer need the allocation setup code to care about what AGs we
might already have locked.

Hence we can remove all the "nullfb" conditional logic in places
like xfs_bmap_btalloc() and instead have them focus simply on
setting up locality constraints. If the allocation fails due to
AGF lock filtering in xfs_alloc_vextent, then we just fall back as
we normally do to more relaxed allocation constraints.

As a result, any allocation that allows AG scanning (i.e. not
confined to a single AG) and does not force a worst case full
filesystem scan will now be able to attempt allocation from AGs
lower than that defined by tp->t_firstblock. This is because
xfs_alloc_vextent() allows try-locking of the AGFs and hence enables
low space algorithms to at least -try- to get space from AGs lower
than the one that we have currently locked and allocated from. This
is a significant improvement in the low space allocation algorithm.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: block reservation too large for minleft allocation
Dave Chinner [Tue, 9 May 2023 09:29:36 +0000 (11:29 +0200)] 
xfs: block reservation too large for minleft allocation

Source kernel commit: d5753847b216db0e553e8065aa825cfe497ad143

When we enter xfs_bmbt_alloc_block() without having first allocated
a data extent (i.e. tp->t_firstblock == NULLFSBLOCK) because we
are doing something like unwritten extent conversion, the transaction
block reservation is used as the minleft value.

This works for operations like unwritten extent conversion, but it
assumes that the block reservation is only for a BMBT split. THis is
not always true, and sometimes results in larger than necessary
minleft values being set. We only actually need enough space for a
btree split, something we already handle correctly in
xfs_bmapi_write() via the xfs_bmapi_minleft() calculation.

We should use xfs_bmapi_minleft() in xfs_bmbt_alloc_block() to
calculate the number of blocks a BMBT split on this inode is going to
require, not use the transaction block reservation that contains the
maximum number of blocks this transaction may consume in it...

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: prefer free inodes at ENOSPC over chunk allocation
Dave Chinner [Tue, 9 May 2023 09:28:48 +0000 (11:28 +0200)] 
xfs: prefer free inodes at ENOSPC over chunk allocation

Source kernel commit: f08f984c63e9980614ae3a0a574b31eaaef284b2

When an XFS filesystem has free inodes in chunks already allocated
on disk, it will still allocate new inode chunks if the target AG
has no free inodes in it. Normally, this is a good idea as it
preserves locality of all the inodes in a given directory.

However, at ENOSPC this can lead to using the last few remaining
free filesystem blocks to allocate a new chunk when there are many,
many free inodes that could be allocated without consuming free
space. This results in speeding up the consumption of the last few
blocks and inode create operations then returning ENOSPC when there
free inodes available because we don't have enough block left in the
filesystem for directory creation reservations to proceed.

Hence when we are near ENOSPC, we should be attempting to preserve
the remaining blocks for directory block allocation rather than
using them for unnecessary inode chunk creation.

This particular behaviour is exposed by xfs/294, when it drives to
ENOSPC on empty file creation whilst there are still thousands of
free inodes available for allocation in other AGs in the filesystem.

Hence, when we are within 1% of ENOSPC, change the inode allocation
behaviour to prefer to use existing free inodes over allocating new
inode chunks, even though it results is poorer locality of the data
set. It is more important for the allocations to be space efficient
near ENOSPC than to have optimal locality for performance, so lets
modify the inode AG selection code to reflect that fact.

This allows generic/294 to not only pass with this allocator rework
patchset, but to increase the number of post-ENOSPC empty inode
allocations to from ~600 to ~9080 before we hit ENOSPC on the
directory create transaction reservation.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: fix low space alloc deadlock
Dave Chinner [Tue, 9 May 2023 09:27:48 +0000 (11:27 +0200)] 
xfs: fix low space alloc deadlock

Source kernel commit: 1dd0510f6d4b85616a36aabb9be38389467122d9

I've recently encountered an ABBA deadlock with g/476. The upcoming
changes seem to make this much easier to hit, but the underlying
problem is a pre-existing one.

Essentially, if we select an AG for allocation, then lock the AGF
and then fail to allocate for some reason (e.g. minimum length
requirements cannot be satisfied), then we drop out of the
allocation with the AGF still locked.

The caller then modifies the allocation constraints - usually
loosening them up - and tries again. This can result in trying to
access AGFs that are lower than the AGF we already have locked from
the failed attempt. e.g. the failed attempt skipped several AGs
before failing, so we have locks an AG higher than the start AG.
Retrying the allocation from the start AG then causes us to violate
AGF lock ordering and this can lead to deadlocks.

The deadlock exists even if allocation succeeds - we can do a
followup allocations in the same transaction for BMBT blocks that
aren't guaranteed to be in the same AG as the original, and can move
into higher AGs. Hence we really need to move the tp->t_firstblock
tracking down into xfs_alloc_vextent() where it can be set when we
exit with a locked AG.

xfs_alloc_vextent() can also check there if the requested
allocation falls within the allow range of AGs set by
tp->t_firstblock. If we can't allocate within the range set, we have
to fail the allocation. If we are allowed to to non-blocking AGF
locking, we can ignore the AG locking order limitations as we can
use try-locks for the first iteration over requested AG range.

This invalidates a set of post allocation asserts that check that
the allocation is always above tp->t_firstblock if it is set.
Because we can use try-locks to avoid the deadlock in some
circumstances, having a pre-existing locked AGF doesn't always
prevent allocation from lower order AGFs. Hence those ASSERTs need
to be removed.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: don't use BMBT btree split workers for IO completion
Dave Chinner [Tue, 2 May 2023 13:11:13 +0000 (15:11 +0200)] 
xfs: don't use BMBT btree split workers for IO completion

Source kernel commit: c85007e2e3942da1f9361e4b5a9388ea3a8dcc5b

When we split a BMBT due to record insertion, we offload it to a
worker thread because we can be deep in the stack when we try to
allocate a new block for the BMBT. Allocation can use several
kilobytes of stack (full memory reclaim, swap and/or IO path can
end up on the stack during allocation) and we can already be several
kilobytes deep in the stack when we need to split the BMBT.

A recent workload demonstrated a deadlock in this BMBT split
offload. It requires several things to happen at once:

1. two inodes need a BMBT split at the same time, one must be
unwritten extent conversion from IO completion, the other must be
from extent allocation.

2. there must be a no available xfs_alloc_wq worker threads
available in the worker pool.

3. There must be sustained severe memory shortages such that new
kworker threads cannot be allocated to the xfs_alloc_wq pool for
both threads that need split work to be run

4. The split work from the unwritten extent conversion must run
first.

5. when the BMBT block allocation runs from the split work, it must
loop over all AGs and not be able to either trylock an AGF
successfully, or each AGF is is able to lock has no space available
for a single block allocation.

6. The BMBT allocation must then attempt to lock the AGF that the
second task queued to the rescuer thread already has locked before
it finds an AGF it can allocate from.

At this point, we have an ABBA deadlock between tasks queued on the
xfs_alloc_wq rescuer thread and a locked AGF. i.e. The queued task
holding the AGF lock can't be run by the rescuer thread until the
task the rescuer thread is runing gets the AGF lock....

This is a highly improbably series of events, but there it is.

There's a couple of ways to fix this, but the easiest way to ensure
that we only punt tasks with a locked AGF that holds enough space
for the BMBT block allocations to the worker thread.

This works for unwritten extent conversion in IO completion (which
doesn't have a locked AGF and space reservations) because we have
tight control over the IO completion stack. It is typically only 6
functions deep when xfs_btree_split() is called because we've
already offloaded the IO completion work to a worker thread and
hence we don't need to worry about stack overruns here.

The other place we can be called for a BMBT split without a
preceeding allocation is __xfs_bunmapi() when punching out the
center of an existing extent. We don't remove extents in the IO
path, so these operations don't tend to be called with a lot of
stack consumed. Hence we don't really need to ship the split off to
a worker thread in these cases, either.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: pass refcount intent directly through the log intent code
Darrick J. Wong [Tue, 2 May 2023 13:10:13 +0000 (15:10 +0200)] 
xfs: pass refcount intent directly through the log intent code

Source kernel commit: 0b11553ec54a6d88907e60d0595dbcef98539747

Pass the incore refcount intent through the CUI logging code instead of
repeatedly boxing and unboxing parameters.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: pass rmap space mapping directly through the log intent code
Darrick J. Wong [Tue, 2 May 2023 12:51:18 +0000 (14:51 +0200)] 
xfs: pass rmap space mapping directly through the log intent code

Source kernel commit: 1534328bb427f175e5de56c9af62f8f4675da595

Pass the incore rmap space mapping through the RUI logging code instead
of repeatedly boxing and unboxing parameters.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: fix confusing xfs_extent_item variable names
Darrick J. Wong [Tue, 2 May 2023 12:29:59 +0000 (14:29 +0200)] 
xfs: fix confusing xfs_extent_item variable names

Source kernel commit: 578c714b215d474c52949e65a914dae67924f0fe

Change the name of all pointers to xfs_extent_item structures to "xefi"
to make the name consistent and because the current selections ("new"
and "free") mean other things in C.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: pass the xfs_bmbt_irec directly through the log intent code
Darrick J. Wong [Tue, 2 May 2023 12:29:04 +0000 (14:29 +0200)] 
xfs: pass the xfs_bmbt_irec directly through the log intent code

Source kernel commit: ddccb81b26ec021ae1f3366aa996cc4c68dd75ce

Instead of repeatedly boxing and unboxing the incore extent mapping
structure as it passes through the BUI code, pass the pointer directly
through.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfsprogs: nrext64 option should be in [inode] section of mkfs conf files
Eric Sandeen [Thu, 20 Apr 2023 14:01:01 +0000 (09:01 -0500)] 
xfsprogs: nrext64 option should be in [inode] section of mkfs conf files

nrext64 is an inode (-i) section option, not a metadata (-m) section option.

Reported-by: Marcos Mello <marcosfrm@gmail.com>
Fixes: 69e7272213 ("mkfs: Add option to create filesystem with large extent counters")
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Chandan Babu R <chandan.babu@oracle.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agomisc: test the dir/attr hash before formatting or repairing fs
Darrick J. Wong [Thu, 6 Apr 2023 00:08:02 +0000 (17:08 -0700)] 
misc: test the dir/attr hash before formatting or repairing fs

Back in the 6.2-rc1 days, Eric Whitney reported a fstests regression in
ext4 against generic/454.  The cause of this test failure was the
unfortunate combination of setting an xattr name containing UTF8 encoded
emoji, an xattr hash function that accepted a char pointer with no
explicit signedness, signed type extension of those chars to an int, and
the 6.2 build tools maintainers deciding to mandate -funsigned-char
across the board.  As a result, the ondisk extended attribute structure
written out by 6.1 and 6.2 were not the same.

This discrepancy, in fact, had been noticeable if a filesystem with such
an xattr were moved between any two architectures that don't employ the
same signedness of a raw "char" declaration.  The only reason anyone
noticed is that x86 gcc defaults to signed, and no such -funsigned-char
update was made to e2fsprogs, so e2fsck immediately started reporting
data corruption.

After a day and a half of discussing how to handle this use case (xattrs
with bit 7 set anywhere in the name) without breaking existing users,
Linus merged his own patch and didn't tell the mailing list.  None of
the developers noticed until AUTOSEL made an announcement.

In the end, this problem could have been detected much earlier if there
had been any useful tests of hash function(s) in use inside ext4 to make
sure that they always produce the same outputs given the same inputs.

The XFS dirent/xattr name hash takes a uint8_t*, so I don't think it's
vulnerable to this problem.  However, let's avoid all this drama by
adding our own self test to check that the da hash produces the same
outputs for a static pile of inputs on various platforms.  This
corresponds to the similar patch for the kernel.

Link: https://lore.kernel.org/linux-ext4/Y8bpkm3jA3bDm3eL@debian-BULLSEYE-live-builder-AMD64/
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>