diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 6e448f50cef45cd9b9e4ea75f280c76b41a27e89..4dd3238161cf3fa2af89efda39247267c9bea581 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -586,6 +586,13 @@ xfs_alloc_fixup_trees( nfbno2 = rbno + rlen; nflen2 = (fbno + flen) - nfbno2; } + + /* + * Record the potential maximum free length in advance. + */ + if (nfbno1 != NULLAGBLOCK || nfbno2 != NULLAGBLOCK) + cnt_cur->bc_ag.bc_free_longest = XFS_EXTLEN_MAX(nflen1, nflen2); + /* * Delete the entry from the by-size btree. */ @@ -2019,6 +2026,13 @@ xfs_free_ag_extent( * Now allocate and initialize a cursor for the by-size tree. */ cnt_cur = xfs_allocbt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_CNT); + /* + * Record the potential maximum free length in advance. + */ + if (haveleft) + cnt_cur->bc_ag.bc_free_longest = ltlen; + if (haveright) + cnt_cur->bc_ag.bc_free_longest = gtlen; /* * Have both left and right contiguous neighbors. * Merge all three into a single free block. diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c index c65228efed4aeca98b645aefa01dd70892601168..d2c7a217a74b15a41ca2f8ebd4746563280c7304 100644 --- a/fs/xfs/libxfs/xfs_alloc_btree.c +++ b/fs/xfs/libxfs/xfs_alloc_btree.c @@ -146,7 +146,14 @@ xfs_allocbt_update_lastrec( rrp = XFS_ALLOC_REC_ADDR(cur->bc_mp, block, numrecs); len = rrp->ar_blockcount; } else { - len = 0; + /* + * Update in advance to prevent file creation failure + * for concurrent processes even though there is no + * numrec currently. + * And there's no need to worry as the value that no + * less than bc_free_longest will be inserted later. + */ + len = cpu_to_be32(cur->bc_ag.bc_free_longest); } break; diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 4d68a58be160cf86452d4fbb21eaf1b2de8fe6a3..bf63bbcd49143619b83efbaefd02bbf534906bb0 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -218,6 +218,7 @@ union xfs_btree_irec { /* Per-AG btree information. */ struct xfs_btree_cur_ag { struct xfs_perag *pag; + xfs_extlen_t bc_free_longest; /* the potential longest free extent */ union { struct xfs_buf *agbp; struct xbtree_afakeroot *afake; /* for staging cursor */