| From hch@lst.de Mon Sep 18 10:09:24 2017 |
| From: Christoph Hellwig <hch@lst.de> |
| Date: Sun, 17 Sep 2017 14:06:40 -0700 |
| Subject: xfs: fix multi-AG deadlock in xfs_bunmapi |
| To: stable@vger.kernel.org |
| Cc: linux-xfs@vger.kernel.org, "Darrick J . Wong" <darrick.wong@oracle.com> |
| Message-ID: <20170917210712.10804-16-hch@lst.de> |
| |
| |
| commit 5b094d6dac0451ad89b1dc088395c7b399b7e9e8 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: 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/xfs/libxfs/xfs_bmap.c | 12 ++++++++++++ |
| 1 file changed, 12 insertions(+) |
| |
| --- a/fs/xfs/libxfs/xfs_bmap.c |
| +++ b/fs/xfs/libxfs/xfs_bmap.c |
| @@ -5556,6 +5556,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_); |
| |
| @@ -5658,6 +5659,17 @@ __xfs_bunmapi( |
| ASSERT(ep != NULL); |
| 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; |