Commit 22998015 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Greg Kroah-Hartman

xfs: fix multi-AG deadlock in xfs_bunmapi

commit 5b094d6d upstream.

Just like in the allocator we must avoid touching multiple AGs out of
order when freeing blocks, as freeing still locks the AGF and can cause
the same AB-BA deadlocks as in the allocation path.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reported-by: default avatarNikolay Borisov <n.borisov.lkml@gmail.com>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 81e27c94
...@@ -5556,6 +5556,7 @@ __xfs_bunmapi( ...@@ -5556,6 +5556,7 @@ __xfs_bunmapi(
xfs_fsblock_t sum; xfs_fsblock_t sum;
xfs_filblks_t len = *rlen; /* length to unmap in file */ xfs_filblks_t len = *rlen; /* length to unmap in file */
xfs_fileoff_t max_len; xfs_fileoff_t max_len;
xfs_agnumber_t prev_agno = NULLAGNUMBER, agno;
trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_); trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_);
...@@ -5658,6 +5659,17 @@ __xfs_bunmapi( ...@@ -5658,6 +5659,17 @@ __xfs_bunmapi(
ASSERT(ep != NULL); ASSERT(ep != NULL);
del = got; del = got;
wasdel = isnullstartblock(del.br_startblock); wasdel = isnullstartblock(del.br_startblock);
/*
* 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) {
agno = XFS_FSB_TO_AGNO(mp, del.br_startblock);
if (prev_agno != NULLAGNUMBER && prev_agno > agno)
break;
prev_agno = agno;
}
if (got.br_startoff < start) { if (got.br_startoff < start) {
del.br_startoff = start; del.br_startoff = start;
del.br_blockcount -= start - got.br_startoff; del.br_blockcount -= start - got.br_startoff;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment