Recently, we encounter a deadlock case where there are many tasks hung on agi and agf xfs_buf. It end up with a deadlock between agf and inode xfs_buf as following, xfs_ifree() xfs_bmap_btalloc() xfs_iunlink_remove() xfs_alloc_vextent() hold inode bp hold agf xfs_difree() xfs_trans_log_inode() require agf require inode bp The task requires inode bp with agf held block other tasks which want to require agf with agi held. Then the whole filesystem looks like a agi/agf deadlock. To fix this issue, get agf in xfs_iunlink_remove() after it get agi and before get indoe bp. Signed-off-by: Wang Jianchao (Kuaishou) <jianchao.wan9@xxxxxxxxx> --- fs/xfs/xfs_inode.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 9de6205fe134..c0a29fd00b0e 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -36,6 +36,7 @@ #include "xfs_reflink.h" #include "xfs_ag.h" #include "xfs_log_priv.h" +#include "xfs_alloc.h" struct kmem_cache *xfs_inode_cache; @@ -2337,6 +2338,7 @@ xfs_iunlink_remove( { struct xfs_mount *mp = tp->t_mountp; struct xfs_agi *agi; + struct xfs_buf *agfbp; struct xfs_buf *agibp; struct xfs_buf *last_ibp; struct xfs_dinode *last_dip = NULL; @@ -2352,6 +2354,14 @@ xfs_iunlink_remove( error = xfs_read_agi(mp, tp, pag->pag_agno, &agibp); if (error) return error; + + /* + * Get the agf buffer first to ensure the lock ordering against inode bp + */ + error = xfs_read_agf(mp, tp, pag->pag_agno, 0, &agfbp); + if (error) + return error; + agi = agibp->b_addr; /* -- 2.17.1