aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2017-07-31 15:08:13 -0500
committerEric Sandeen <sandeen@redhat.com>2017-07-31 15:08:13 -0500
commit15a8bccc9403c0ab1dbe869aa3afce7be9e1dd49 (patch)
tree387f9b5918dcebac973f995cce88e710a04daf36
parentf9f5e90c212052f896cc2ffbbb062498dd026b1a (diff)
downloadxfsprogs-dev-15a8bccc9403c0ab1dbe869aa3afce7be9e1dd49.tar.gz
xfs: fix multi-AG deadlock in xfs_bunmapi
Source kernel commit: 5b094d6dac0451ad89b1dc088395c7b399b7e9e8 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> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--libxfs/xfs_bmap.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index d11e4d6567..e26bd239c4 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -5426,6 +5426,7 @@ __xfs_bunmapi(
xfs_fsblock_t sum;
xfs_filblks_t len = *rlen; /* length to unmap in file */
xfs_fileoff_t max_len;
+ xfs_agnumber_t prev_agno = NULLAGNUMBER, agno;
trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_);
@@ -5525,6 +5526,17 @@ __xfs_bunmapi(
*/
del = got;
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) {
del.br_startoff = start;
del.br_blockcount -= start - got.br_startoff;