Fixes for 5.13-rc4:
- Fix a bug where unmapping operations end earlier than expected, which
  can cause chaos on multi-block directory and symlink shrink
- Fix an erroneous assert that can trigger if we try to transition a
  bmap structure from btree format to extents format with zero extents.
  This was exposed by xfs/538.
xfs: bunmapi has unnecessary AG lock ordering issues

large directory block size operations are assert failing because
xfs_bunmapi() is not completely removing fragmented directory blocks
like so:

XFS: Assertion failed: done, file: fs/xfs/libxfs/xfs_dir2.c, line: 677
Call Trace:
 ? avc_has_perm+0x8d/0x1a0
 ? avc_has_perm_noaudit+0x9a/0x120
 ? __lookup_hash+0x6a/0xa0

We are aborting the bunmapi() pass because of this specific chunk of

                 * Make sure we don't touch multiple AGF headers out of order
                 * in a single transaction, as that could cause AB-BA deadlocks.
                if (!wasdel && !isrt) {
                        agno = XFS_FSB_TO_AGNO(mp, del.br_startblock);
                        if (prev_agno != NULLAGNUMBER && prev_agno > agno)
                        prev_agno = agno;

This is designed to prevent deadlocks in AGF locking when freeing
multiple extents by ensuring that we only ever lock in increasing
AG number order. Unfortunately, this also violates the "bunmapi will
always succeed" semantic that some high level callers depend on,
such as xfs_dir2_shrink_inode(), xfs_da_shrink_inode() and

This AG lock ordering was introduced back in 2017 to fix deadlocks
triggered by generic/299 as reported here:

This codebase is old enough that it was before we were defering all
AG based extent freeing from within xfs_bunmapi(). THat is, we never
actually lock AGs in xfs_bunmapi() any more - every non-rt based
extent free is added to the defer ops list, as is all BMBT block
freeing. And RT extents are not RT based, so there's no lock
ordering issues associated with them.

Hence this AGF lock ordering code is both broken and dead. Let's
just remove it so that the large directory block code works reliably

Tested against xfs/538 and generic/299 which is the original test
that exposed the deadlocks that this code fixed.

Fixes: 5b094d6dac04 ("xfs: fix multi-AG deadlock in xfs_bunmapi")
Signed-off-by: Dave Chinner <>
Reviewed-by: Darrick J. Wong <>
Signed-off-by: Darrick J. Wong <>
1 file changed