Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: make xfs_*read_agf return EAGAIN to ALLOC_FLAG_TRYLOCK callers

Refactor xfs_read_agf and xfs_alloc_read_agf to return EAGAIN if the
caller passed TRYLOCK and we weren't able to get the lock; and change
the callers to recognize this.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>

+25 -33
+14 -22
fs/xfs/libxfs/xfs_alloc.c
··· 2502 2502 2503 2503 if (!pag->pagf_init) { 2504 2504 error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); 2505 - if (error) 2505 + if (error) { 2506 + /* Couldn't lock the AGF so skip this AG. */ 2507 + if (error == -EAGAIN) 2508 + error = 0; 2506 2509 goto out_no_agbp; 2507 - if (!pag->pagf_init) { 2508 - ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); 2509 - ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); 2510 - goto out_agbp_relse; 2511 2510 } 2512 2511 } 2513 2512 ··· 2532 2533 */ 2533 2534 if (!agbp) { 2534 2535 error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); 2535 - if (error) 2536 - goto out_no_agbp; 2537 - if (!agbp) { 2538 - ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); 2539 - ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); 2536 + if (error) { 2537 + /* Couldn't lock the AGF so skip this AG. */ 2538 + if (error == -EAGAIN) 2539 + error = 0; 2540 2540 goto out_no_agbp; 2541 2541 } 2542 2542 } ··· 2766 2768 xfs_buf_t *bp; 2767 2769 int error; 2768 2770 2769 - if ((error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp))) 2770 - return error; 2771 - if (bp) 2771 + error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp); 2772 + if (!error) 2772 2773 xfs_trans_brelse(tp, bp); 2773 - return 0; 2774 + return error; 2774 2775 } 2775 2776 2776 2777 /* ··· 2958 2961 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, 2959 2962 XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), 2960 2963 XFS_FSS_TO_BB(mp, 1), flags, bpp, &xfs_agf_buf_ops); 2961 - /* 2962 - * Callers of xfs_read_agf() currently interpret a NULL bpp as EAGAIN 2963 - * and need to be converted to check for EAGAIN specifically. 2964 - */ 2965 - if (error == -EAGAIN) 2966 - return 0; 2967 2964 if (error) 2968 2965 return error; 2969 2966 ··· 2983 2992 2984 2993 trace_xfs_alloc_read_agf(mp, agno); 2985 2994 2995 + /* We don't support trylock when freeing. */ 2996 + ASSERT((flags & (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)) != 2997 + (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)); 2986 2998 ASSERT(agno != NULLAGNUMBER); 2987 2999 error = xfs_read_agf(mp, tp, agno, 2988 3000 (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0, 2989 3001 bpp); 2990 3002 if (error) 2991 3003 return error; 2992 - if (!*bpp) 2993 - return 0; 2994 3004 ASSERT(!(*bpp)->b_error); 2995 3005 2996 3006 agf = XFS_BUF_TO_AGF(*bpp);
+6 -5
fs/xfs/libxfs/xfs_bmap.c
··· 3311 3311 pag = xfs_perag_get(mp, ag); 3312 3312 if (!pag->pagf_init) { 3313 3313 error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK); 3314 - if (error) 3315 - goto out; 3316 - 3317 - if (!pag->pagf_init) { 3318 - *notinit = 1; 3314 + if (error) { 3315 + /* Couldn't lock the AGF, so skip this AG. */ 3316 + if (error == -EAGAIN) { 3317 + *notinit = 1; 3318 + error = 0; 3319 + } 3319 3320 goto out; 3320 3321 } 3321 3322 }
+5 -6
fs/xfs/xfs_filestream.c
··· 159 159 160 160 if (!pag->pagf_init) { 161 161 err = xfs_alloc_pagf_init(mp, NULL, ag, trylock); 162 - if (err && !trylock) { 162 + if (err) { 163 163 xfs_perag_put(pag); 164 - return err; 164 + if (err != -EAGAIN) 165 + return err; 166 + /* Couldn't lock the AGF, skip this AG. */ 167 + continue; 165 168 } 166 169 } 167 - 168 - /* Might fail sometimes during the 1st pass with trylock set. */ 169 - if (!pag->pagf_init) 170 - goto next_ag; 171 170 172 171 /* Keep track of the AG with the most free blocks. */ 173 172 if (pag->pagf_freeblks > maxfree) {