From: Baokun Li libaokun1@huawei.com
hulk inclusion category: bugfix bugzilla: 188871, https://gitee.com/openeuler/kernel/issues/I76JSK CVE: NA
--------------------------------
xfs_alloc_ag_vextent_near() may keep restarting after xfs shutdown, triggering soft lockup, because although xfs_log_force() detects that the current filesystem has been shut down and returns an error, but xfs_extent_busy _flush() is a void function, so xfs_alloc_ag_vextent_near() does not sense that the current filesystem has been shut down. So we avoid this problem by propagating the return value of xfs_log_force() so that xfs_alloc_ag_vextent_near() does not restart and retry when the file system is shut down, and exits directly.
Signed-off-by: Baokun Li libaokun1@huawei.com Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/libxfs/xfs_alloc.c | 22 ++++++++++++++++------ fs/xfs/xfs_extent_busy.c | 6 ++++-- fs/xfs/xfs_extent_busy.h | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 60aab422e818..c90324354e3e 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1629,8 +1629,11 @@ xfs_alloc_ag_vextent_near( if (!acur.len) { if (acur.busy) { trace_xfs_alloc_near_busy(args); - xfs_extent_busy_flush(args->mp, args->pag, + error = xfs_extent_busy_flush(args->mp, args->pag, acur.busy_gen); + if (error) + goto out; + goto restart; } trace_xfs_alloc_size_neither(args); @@ -1733,11 +1736,14 @@ xfs_alloc_ag_vextent_size( * Make it unbusy by forcing the log out and * retrying. */ - xfs_btree_del_cursor(cnt_cur, - XFS_BTREE_NOERROR); trace_xfs_alloc_size_busy(args); - xfs_extent_busy_flush(args->mp, + error = xfs_extent_busy_flush(args->mp, args->pag, busy_gen); + if (error) + goto error0; + + xfs_btree_del_cursor(cnt_cur, + XFS_BTREE_NOERROR); goto restart; } } @@ -1819,9 +1825,13 @@ xfs_alloc_ag_vextent_size( args->len = rlen; if (rlen < args->minlen) { if (busy) { - xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); trace_xfs_alloc_size_busy(args); - xfs_extent_busy_flush(args->mp, args->pag, busy_gen); + error = xfs_extent_busy_flush(args->mp, args->pag, + busy_gen); + if (error) + goto error0; + + xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); goto restart; } goto out_nominleft; diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c index 26680444969c..ea3cee00149a 100644 --- a/fs/xfs/xfs_extent_busy.c +++ b/fs/xfs/xfs_extent_busy.c @@ -579,7 +579,7 @@ xfs_extent_busy_clear( /* * Flush out all busy extents for this AG. */ -void +int xfs_extent_busy_flush( struct xfs_mount *mp, struct xfs_perag *pag, @@ -590,7 +590,7 @@ xfs_extent_busy_flush(
error = xfs_log_force(mp, XFS_LOG_SYNC); if (error) - return; + return error;
do { prepare_to_wait(&pag->pagb_wait, &wait, TASK_KILLABLE); @@ -600,6 +600,8 @@ xfs_extent_busy_flush( } while (1);
finish_wait(&pag->pagb_wait, &wait); + + return 0; }
void diff --git a/fs/xfs/xfs_extent_busy.h b/fs/xfs/xfs_extent_busy.h index 8aea07100092..7099f4bb358c 100644 --- a/fs/xfs/xfs_extent_busy.h +++ b/fs/xfs/xfs_extent_busy.h @@ -50,7 +50,7 @@ bool xfs_extent_busy_trim(struct xfs_alloc_arg *args, xfs_agblock_t *bno, xfs_extlen_t *len, unsigned *busy_gen);
-void +int xfs_extent_busy_flush(struct xfs_mount *mp, struct xfs_perag *pag, unsigned busy_gen);