Commit 5b094d6d authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Darrick J. Wong

xfs: fix multi-AG deadlock in xfs_bunmapi

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>
parent 6215894e
...@@ -5435,6 +5435,7 @@ __xfs_bunmapi( ...@@ -5435,6 +5435,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_);
...@@ -5534,6 +5535,17 @@ __xfs_bunmapi( ...@@ -5534,6 +5535,17 @@ __xfs_bunmapi(
*/ */
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