]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: fix multi-AG deadlock in xfs_bunmapi
authorChristoph Hellwig <hch@lst.de>
Mon, 31 Jul 2017 20:08:13 +0000 (15:08 -0500)
committerEric Sandeen <sandeen@redhat.com>
Mon, 31 Jul 2017 20:08:13 +0000 (15:08 -0500)
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>
libxfs/xfs_bmap.c

index d11e4d6567cdee4cdb018acafb4f0d11c7db435a..e26bd239c40781da9db913099be6703763d46d34 100644 (file)
@@ -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;