aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2017-07-18 14:16:51 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2017-07-26 11:20:03 -0400
commit5b094d6dac0451ad89b1dc088395c7b399b7e9e8 (patch)
tree83ef91fc22af5f57c4f08902ec92b3d432d0f1b9
parent6215894e11de224183c89b001f5363912442b489 (diff)
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: Christoph Hellwig <hch@lst.de> Reported-by: Nikolay Borisov <n.borisov.lkml@gmail.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index ee118ceb702f..c09c16b1ad3b 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -5435,6 +5435,7 @@ __xfs_bunmapi(
5435 xfs_fsblock_t sum; 5435 xfs_fsblock_t sum;
5436 xfs_filblks_t len = *rlen; /* length to unmap in file */ 5436 xfs_filblks_t len = *rlen; /* length to unmap in file */
5437 xfs_fileoff_t max_len; 5437 xfs_fileoff_t max_len;
5438 xfs_agnumber_t prev_agno = NULLAGNUMBER, agno;
5438 5439
5439 trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_); 5440 trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_);
5440 5441
@@ -5534,6 +5535,17 @@ __xfs_bunmapi(
5534 */ 5535 */
5535 del = got; 5536 del = got;
5536 wasdel = isnullstartblock(del.br_startblock); 5537 wasdel = isnullstartblock(del.br_startblock);
5538
5539 /*
5540 * Make sure we don't touch multiple AGF headers out of order
5541 * in a single transaction, as that could cause AB-BA deadlocks.
5542 */
5543 if (!wasdel) {
5544 agno = XFS_FSB_TO_AGNO(mp, del.br_startblock);
5545 if (prev_agno != NULLAGNUMBER && prev_agno > agno)
5546 break;
5547 prev_agno = agno;
5548 }
5537 if (got.br_startoff < start) { 5549 if (got.br_startoff < start) {
5538 del.br_startoff = start; 5550 del.br_startoff = start;
5539 del.br_blockcount -= start - got.br_startoff; 5551 del.br_blockcount -= start - got.br_startoff;