]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/log
thirdparty/xfsprogs-dev.git
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>
2 years agolibfrog: move crc32c selftest buffer into a separate file
Darrick J. Wong [Thu, 6 Apr 2023 00:07:56 +0000 (17:07 -0700)] 
libfrog: move crc32c selftest buffer into a separate file

Move the random buffer used for selftests into a separate file so that
we can link to it from multiple places.

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 agoxfsprogs: Release v6.2.0 v6.2.0
Carlos Maiolino [Fri, 24 Mar 2023 10:25:16 +0000 (11:25 +0100)] 
xfsprogs: Release v6.2.0

Update all the necessary files for a 6.2.0 release.

Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: fix off-by-one error in xfs_btree_space_to_height
Darrick J. Wong [Wed, 15 Mar 2023 14:59:35 +0000 (15:59 +0100)] 
xfs: fix off-by-one error in xfs_btree_space_to_height

Source kernel commit: c0f399ff51495ac8d30367418f4f6292ecd61fbe

Lately I've been stress-testing extreme-sized rmap btrees by using the
(new) xfs_db bmap_inflate command to clone bmbt mappings billions of
times and then using xfs_repair to build new rmap and refcount btrees.
This of course is /much/ faster than actually FICLONEing a file billions
of times.

Unfortunately, xfs_repair fails in xfs_btree_bload_compute_geometry with
EOVERFLOW, which indicates that xfs_mount.m_rmap_maxlevels is not
sufficiently large for the test scenario.  For a 1TB filesystem (~67
million AG blocks, 4 AGs) the btheight command reports:

$ xfs_db -c 'btheight -n 4400801200 -w min rmapbt' /dev/sda
rmapbt: worst case per 4096-byte block: 84 records (leaf) / 45 keyptrs (node)
level 0: 4400801200 records, 52390491 blocks
level 1: 52390491 records, 1164234 blocks
level 2: 1164234 records, 25872 blocks
level 3: 25872 records, 575 blocks
level 4: 575 records, 13 blocks
level 5: 13 records, 1 block
6 levels, 53581186 blocks total

The AG is sufficiently large to build this rmap btree.  Unfortunately,
m_rmap_maxlevels is 5.  Augmenting the loop in the space->height
function to report height, node blocks, and blocks remaining produces
this:

ht 1 node_blocks 45 blockleft 67108863
ht 2 node_blocks 2025 blockleft 67108818
ht 3 node_blocks 91125 blockleft 67106793
ht 4 node_blocks 4100625 blockleft 67015668
final height: 5

The goal of this function is to compute the maximum height btree that
can be stored in the given number of ondisk fsblocks.  Starting with the
top level of the tree, each iteration through the loop adds the fanout
factor of the next level down until we run out of blocks.  IOWs, maximum
height is achieved by using the smallest fanout factor that can apply
to that level.

However, the loop setup is not correct.  Top level btree blocks are
allowed to contain fewer than minrecs items, so the computation is
incorrect because the first time through the loop it should be using a
fanout factor of 2.  With this corrected, the above becomes:

ht 1 node_blocks 2 blockleft 67108863
ht 2 node_blocks 90 blockleft 67108861
ht 3 node_blocks 4050 blockleft 67108771
ht 4 node_blocks 182250 blockleft 67104721
ht 5 node_blocks 8201250 blockleft 66922471
final height: 6

Fixes: 9ec691205e7d ("xfs: compute the maximum height of the rmap btree when reflink enabled")
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: invalidate xfs_bufs when allocating cow extents
Darrick J. Wong [Wed, 15 Mar 2023 14:58:35 +0000 (15:58 +0100)] 
xfs: invalidate xfs_bufs when allocating cow extents

Source kernel commit: ddfdd530e43fcb3f7a0a69966e5f6c33497b4ae3

While investigating test failures in xfs/17[1-3] in alwayscow mode, I
noticed through code inspection that xfs_bmap_alloc_userdata isn't
setting XFS_ALLOC_USERDATA when allocating extents for a file's CoW
fork.  COW staging extents should be flagged as USERDATA, since user
data are persisted to these blocks before being remapped into a file.

This mis-classification has a few impacts on the behavior of the system.
First, the filestreams allocator is supposed to keep allocating from a
chosen AG until it runs out of space in that AG.  However, it only does
that for USERDATA allocations, which means that COW allocations aren't
tied to the filestreams AG.  Fortunately, few people use filestreams, so
nobody's noticed.

A more serious problem is that xfs_alloc_ag_vextent_small looks for a
buffer to invalidate *if* the USERDATA flag is set and the AG is so full
that the allocation had to come from the AGFL because the cntbt is
empty.  The consequences of not invalidating the buffer are severe --
if the AIL incorrectly checkpoints a buffer that is now being used to
store user data, that action will clobber the user's written data.

Fix filestreams and yet another data corruption vector by flagging COW
allocations as USERDATA.

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: get rid of assert from xfs_btree_islastblock
Guo Xuenan [Wed, 15 Mar 2023 14:57:35 +0000 (15:57 +0100)] 
xfs: get rid of assert from xfs_btree_islastblock

Source kernel commit: 8c25febf23963431686f04874b96321288504127

xfs_btree_check_block contains debugging knobs. With XFS_DEBUG setting up,
turn on the debugging knob can trigger the assert of xfs_btree_islastblock,
test script as follows:

while true
do
mount $disk $mountpoint
fsstress -d $testdir -l 0 -n 10000 -p 4 >/dev/null
echo 1 > /sys/fs/xfs/sda/errortag/btree_chk_sblk
sleep 10
umount $mountpoint
done

Kick off fsstress and only *then* turn on the debugging knob. If it
happens that the knob gets turned on after the cntbt lookup succeeds
but before the call to xfs_btree_islastblock, then we *can* end up in
the situation where a previously checked btree block suddenly starts
returning EFSCORRUPTED from xfs_btree_check_block. Kaboom.

Darrick give a very detailed explanation as follows:
Looking back at commit 27d9ee577dcce, I think the point of all this was
to make sure that the cursor has actually performed a lookup, and that
the btree block at whatever level we're asking about is ok.

If the caller hasn't ever done a lookup, the bc_levels array will be
empty, so cur->bc_levels[level].bp pointer will be NULL.  The call to
xfs_btree_get_block will crash anyway, so the "ASSERT(block);" part is
pointless.

If the caller did a lookup but the lookup failed due to block
corruption, the corresponding cur->bc_levels[level].bp pointer will also
be NULL, and we'll still crash.  The "ASSERT(xfs_btree_check_block);"
logic is also unnecessary.

If the cursor level points to an inode root, the block buffer will be
incore, so it had better always be consistent.

If the caller ignores a failed lookup after a successful one and calls
this function, the cursor state is garbage and the assert wouldn't have
tripped anyway. So get rid of the assert.

Fixes: 27d9ee577dcc ("xfs: actually check xfs_btree_check_block return in xfs_btree_islastblock")
Signed-off-by: Guo Xuenan <guoxuenan@huawei.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: estimate post-merge refcounts correctly
Darrick J. Wong [Wed, 15 Mar 2023 14:56:35 +0000 (15:56 +0100)] 
xfs: estimate post-merge refcounts correctly

Source kernel commit: b25d1984aa884fc91a73a5a407b9ac976d441e9b

Upon enabling fsdax + reflink for XFS, xfs/179 began to report refcount
metadata corruptions after being run.  Specifically, xfs_repair noticed
single-block refcount records that could be combined but had not been.

The root cause of this is improper MAXREFCOUNT edge case handling in
xfs_refcount_merge_extents.  When we're trying to find candidates for a
refcount btree record merge, we compute the refcount attribute of the
merged record, but we fail to account for the fact that once a record
hits rc_refcount == MAXREFCOUNT, it is pinned that way forever.  Hence
the computed refcount is wrong, and we fail to merge the extents.

Fix this by adjusting the merge predicates to compute the adjusted
refcount correctly.

Fixes: 3172725814f9 ("xfs: adjust refcount of an extent of blocks in refcount btree")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Xiao Yang <yangx.jy@fujitsu.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: hoist refcount record merge predicates
Darrick J. Wong [Wed, 15 Mar 2023 14:55:35 +0000 (15:55 +0100)] 
xfs: hoist refcount record merge predicates

Source kernel commit: 9d720a5a658f5135861773f26e927449bef93d61

Hoist these multiline conditionals into separate static inline helpers
to improve readability and set the stage for corruption fixes that will
be introduced in the next patch.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Xiao Yang <yangx.jy@fujitsu.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs: add debug knob to slow down write for fun
Darrick J. Wong [Wed, 15 Mar 2023 14:55:23 +0000 (15:55 +0100)] 
xfs: add debug knob to slow down write for fun

Source kernel commit: 254e3459285cbf2174350bbc0051e475e1bc5196

Add a new error injection knob so that we can arbitrarily slow down
pagecache writes to test for race conditions and aberrant reclaim
behavior if the writeback mechanisms are slow to issue writeback.  This
will enable functional testing for the ifork sequence counters
introduced in commit 304a68b9c63b ("xfs: use iomap_valid method to
detect stale cached iomaps") that fixes write racing with reclaim
writeback.

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: add debug knob to slow down writeback for fun
Darrick J. Wong [Wed, 15 Mar 2023 14:53:19 +0000 (15:53 +0100)] 
xfs: add debug knob to slow down writeback for fun

Source kernel commit: c2beff99eb03866df6fdbd3a93b08fd27eb8bf5c

Add a new error injection knob so that we can arbitrarily slow down
writeback to test for race conditions and aberrant reclaim behavior if
the writeback mechanisms are slow to issue writeback.  This will enable
functional testing for the ifork sequence counters introduced in commit
745b3f76d1c8 ("xfs: maintain a sequence count for inode fork
manipulations").

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: drop write error injection is unfixable, remove it
Dave Chinner [Wed, 15 Mar 2023 14:48:04 +0000 (15:48 +0100)] 
xfs: drop write error injection is unfixable, remove it

Source kernel commit: 6e8af15ccdc4e138a5b529c1901a0013e1dcaa09

With the changes to scan the page cache for dirty data to avoid data
corruptions from partial write cleanup racing with other page cache
operations, the drop writes error injection no longer works the same
way it used to and causes xfs/196 to fail. This is because xfs/196
writes to the file and populates the page cache before it turns on
the error injection and starts failing -overwrites-.

The result is that the original drop-writes code failed writes only
-after- overwriting the data in the cache, followed by invalidates
the cached data, then punching out the delalloc extent from under
that data.

On the surface, this looks fine. The problem is that page cache
invalidation *doesn't guarantee that it removes anything from the
page cache* and it doesn't change the dirty state of the folio. When
block size == page size and we do page aligned IO (as xfs/196 does)
everything happens to align perfectly and page cache invalidation
removes the single page folios that span the written data. Hence the
followup delalloc punch pass does not find cached data over that
range and it can punch the extent out.

IOWs, xfs/196 "works" for block size == page size with the new
code. I say "works", because it actually only works for the case
where IO is page aligned, and no data was read from disk before
writes occur. Because the moment we actually read data first, the
readahead code allocates multipage folios and suddenly the
invalidate code goes back to zeroing subfolio ranges without
changing dirty state.

Hence, with multipage folios in play, block size == page size is
functionally identical to block size < page size behaviour, and
drop-writes is manifestly broken w.r.t to this case. Invalidation of
a subfolio range doesn't result in the folio being removed from the
cache, just the range gets zeroed. Hence after we've sequentially
walked over a folio that we've dirtied (via write data) and then
invalidated, we end up with a dirty folio full of zeroed data.

And because the new code skips punching ranges that have dirty
folios covering them, we end up leaving the delalloc range intact
after failing all the writes. Hence failed writes now end up
writing zeroes to disk in the cases where invalidation zeroes folios
rather than removing them from cache.

This is a fundamental change of behaviour that is needed to avoid
the data corruption vectors that exist in the old write fail path,
and it renders the drop-writes injection non-functional and
unworkable as it stands.

As it is, I think the error injection is also now unnecessary, as
partial writes that need delalloc extent are going to be a lot more
common with stale iomap detection in place. Hence this patch removes
the drop-writes error injection completely. xfs/196 can remain for
testing kernels that don't have this data corruption fix, but those
that do will report:

xfs/196 3s ... [not run] XFS error injection drop_writes unknown on this kernel.

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 iomap_valid method to detect stale cached iomaps
Dave Chinner [Wed, 15 Mar 2023 14:47:39 +0000 (15:47 +0100)] 
xfs: use iomap_valid method to detect stale cached iomaps

Source kernel commit: 304a68b9c63bbfc1f6e159d68e8892fc54a06067

Now that iomap supports a mechanism to validate cached iomaps for
buffered write operations, hook it up to the XFS buffered write ops
so that we can avoid data corruptions that result from stale cached
iomaps. See:

https://lore.kernel.org/linux-xfs/20220817093627.GZ3600936@dread.disaster.area/

or the ->iomap_valid() introduction commit for exact details of the
corruption vector.

The validity cookie we store in the iomap is based on the type of
iomap we return. It is expected that the iomap->flags we set in
xfs_bmbt_to_iomap() is not perturbed by the iomap core and are
returned to us in the iomap passed via the .iomap_valid() callback.
This ensures that the validity cookie is always checking the correct
inode fork sequence numbers to detect potential changes that affect
the extent cached by the iomap.

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 agotreewide: use get_random_u32_below() instead of deprecated function
Jason A. Donenfeld [Wed, 15 Mar 2023 14:31:07 +0000 (15:31 +0100)] 
treewide: use get_random_u32_below() instead of deprecated function

Source kernel commit: 8032bf1233a74627ce69b803608e650f3f35971c

This is a simple mechanical transformation done by:

@@
expression E;
@@
- prandom_u32_max
+ get_random_u32_below
(E)

Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Darrick J. Wong <djwong@kernel.org> # for xfs
Reviewed-by: SeongJae Park <sj@kernel.org> # for damon
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> # for infiniband
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> # for arm
Acked-by: Ulf Hansson <ulf.hansson@linaro.org> # for mmc
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_db: fix complaints about unsigned char casting
Darrick J. Wong [Wed, 15 Mar 2023 01:01:10 +0000 (18:01 -0700)] 
xfs_db: fix complaints about unsigned char casting

Make the warnings about signed/unsigned char pointer casting go away.
For printing dirent names it doesn't matter at all.

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: fix incorrect dabtree hashval comparison
Darrick J. Wong [Wed, 15 Mar 2023 01:01:55 +0000 (18:01 -0700)] 
xfs_repair: fix incorrect dabtree hashval comparison

If an xattr structure contains enough names with the same hash value to
fill multiple xattr leaf blocks with names all hashing to the same
value, then the dabtree nodes will contain consecutive entries with the
same hash value.

This causes false corruption reports in xfs_repair because it's not
expecting such a huge same-hashing structure.  Fix that.

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: substitute slashes with spaces in protofiles
Darrick J. Wong [Wed, 1 Mar 2023 16:05:45 +0000 (08:05 -0800)] 
mkfs: substitute slashes with spaces in protofiles

A user requested the ability to specify directory entry names in a
protofile that have spaces in them.  The protofile format itself does
not allow spaces (yay 1973-era protofiles!) but it does allow slashes.
Slashes aren't allowed in directory entry names, so we'll permit this
one gross hack.  After this, the protofile:

/
0 0
d--775 1000 1000
: Descending path /code/t/fstests
 get/isk.sh   ---775 1000 1000 /code/t/fstests/getdisk.sh
$

Will produce "get isk.h" in the root directory when used thusly:

# mkfs.xfs -p slashes_are_spaces=1,/tmp/protofile -f /dev/sda

Requested-by: Daan De Meyer <daan.j.demeyer@gmail.com>
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: use suboption processing for -p
Darrick J. Wong [Wed, 1 Mar 2023 16:05:39 +0000 (08:05 -0800)] 
mkfs: use suboption processing for -p

Use suboption processing for -p so that we can add a few behavioral
variants to protofiles in the next patch.  As a side effect of this
change, one can now provide the path to a protofile in the config
file:

[proto]
file=/tmp/protofile

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: check dirent names when reading protofile
Darrick J. Wong [Wed, 1 Mar 2023 16:05:34 +0000 (08:05 -0800)] 
mkfs: check dirent names when reading protofile

The protofile parser in mkfs does not check directory entry names when
populating the filesystem.  The libxfs directory code doesn't check them
either, since they depend on the Linux VFS to sanitize incoming names.
If someone puts a slash in the first (name) column in the protofile,
this results in a successful format and xfs_repair -n immediately
complains.

Screen the names that are being read from the protofile.

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 agoRemove several implicit function declarations origin/for-next_2023-03-01 origin/for-next_2023-03-14
Arjun Shankar [Wed, 8 Feb 2023 14:34:16 +0000 (15:34 +0100)] 
Remove several implicit function declarations

During configure, several ioctl checks omit the corresponding include
and a pwritev2 check uses the wrong feature test macro.
This commit fixes the same.

Signed-off-by: Arjun Shankar <arjun@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_db: make flist_find_ftyp() to check for field existance on disk
Andrey Albershteyn [Wed, 8 Feb 2023 11:02:22 +0000 (12:02 +0100)] 
xfs_db: make flist_find_ftyp() to check for field existance on disk

flist_find_ftyp() searches for the field of the requested type. The
first found field/path is returned. However, this doesn't work when
there are multiple fields of the same type. For example, attr3 type
have a few CRC fields. Leaf block (xfs_attr_leaf_hdr ->
xfs_da3_blkinfo) and remote value block (xfs_attr3_rmt_hdr) both
have CRC but goes under attr3 type. This causes 'crc' command to be
unable to find CRC field when we are at remote attribute block as it
tries to use leaf block CRC path:

$ dd if=/dev/zero bs=4k count=10 | tr '\000' '1' > test.img
$ touch test.file
$ setfattr -n user.bigattr -v "$(cat test.img)" test.file

$ # CRC of the leaf block
$ xfs_db -r -x /dev/sda5 -c 'inode 132' -c 'ablock 0' -c 'crc'
Verifying CRC:
hdr.info.crc = 0x102b5cbf (correct)

$ # CRC of the remote value block
$ xfs_db -r -x /dev/sda5 -c 'inode 132' -c 'ablock 1' -c 'crc'
field info not found
parsing error

Solve this by making flist_find_ftyp() to also check that field in
question have non-zero count (exist at the current block).

Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_io: fix bmap command not detecting realtime files with xattrs
Darrick J. Wong [Thu, 16 Feb 2023 21:53:10 +0000 (13:53 -0800)] 
xfs_io: fix bmap command not detecting realtime files with xattrs

Fix the bmap command so that it will detect a realtime file if any of
the other file flags (e.g. xattrs) are set.  Observed via xfs/556.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
2 years agoxfs_io: set fs_path when opening files on foreign filesystems
Darrick J. Wong [Thu, 16 Feb 2023 21:53:04 +0000 (13:53 -0800)] 
xfs_io: set fs_path when opening files on foreign filesystems

Ted noticed that the following command:

$ xfs_io -c 'fsmap -d 0 0' /mnt
xfs_io: xfsctl(XFS_IOC_GETFSMAP) iflags=0x0 ["/mnt"]: Invalid argument

doesn't work on an ext4 filesystem.  The above command is supposed to
issue a GETFSMAP query against the "data" device.  Although the manpage
doesn't claim support for ext4, it turns out that this you get this
trace data:

          xfs_io-4144  [002]   210.965642: ext4_getfsmap_low_key: dev
7:0 keydev 163:2567 block 0 len 0 owner 0 flags 0x0
          xfs_io-4144  [002]   210.965645: ext4_getfsmap_high_key: dev
7:0 keydev 32:5277:0 block 0 len 0 owner -1 flags 0xffffffff

Notice the random garbage in the keydev field -- this happens because
openfile (in xfs_io) doesn't initialize *fs_path if the caller doesn't
supply a geometry structure or the opened file isn't on an XFS
filesystem.  IOWs, we feed random heap garbage to the kernel, and the
kernel rejects the call unnecessarily.

Fix this to set the fspath information even for foreign filesystems.

Reported-by: tytso@mit.edu
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_scrub: fix broken realtime free blocks unit conversions
Darrick J. Wong [Thu, 16 Feb 2023 21:52:58 +0000 (13:52 -0800)] 
xfs_scrub: fix broken realtime free blocks unit conversions

r_blocks is in units of fs blocks, but freertx is in units of realtime
extents.  Add the missing conversion factor so we don't end up with
bogus things like this:

Pretend that sda and sdb are both 100T volumes.

# mkfs.xfs -f /dev/sda -b -r rtdev=/dev/sdb,extsize=2m
# mount /dev/sda /mnt -o rtdev=/dev/sdb
# xfs_scrub -dTvn /mnt
<snip>
Phase 7: Check summary counters.
3.5TiB data used;  99.8TiB realtime data used;  55 inodes used.
2.0GiB data found; 50.0MiB realtime data found; 55 inodes found.
55 inodes counted; 0 inodes checked.

We just created the filesystem, the realtime volume should be empty.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>