mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
6215894e11
commit
5b094d6dac
|
@ -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(
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue