From 4ddd8bb1d25f9cbb345e1f64a56c0f641a787ede Mon Sep 17 00:00:00 2001 From: Lachlan McIlroy Date: Fri, 27 Jun 2008 13:32:53 +1000 Subject: [PATCH] [XFS] use minleft when allocating in xfs_bmbt_split() The bmap btree split code relies on a previous data extent allocation (from xfs_bmap_btalloc()) to find an AG that has sufficient space to perform a full btree split, when inserting the extent. When converting unwritten extents we don't allocate a data extent so a btree split will be the first allocation. In this case we need to set minleft so the allocator will pick an AG that has space to complete the split(s). SGI-PV: 983338 SGI-Modid: xfs-linux-melb:xfs-kern:31357a Signed-off-by: Lachlan McIlroy Signed-off-by: David Chinner --- fs/xfs/xfs_bmap_btree.c | 15 ++++++++++++++- fs/xfs/xfs_iomap.c | 10 ++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 4aa2f11ba5..3fc09cd8d5 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -1493,12 +1493,25 @@ xfs_bmbt_split( left = XFS_BUF_TO_BMBT_BLOCK(lbp); args.fsbno = cur->bc_private.b.firstblock; args.firstblock = args.fsbno; + args.minleft = 0; if (args.fsbno == NULLFSBLOCK) { args.fsbno = lbno; args.type = XFS_ALLOCTYPE_START_BNO; + /* + * Make sure there is sufficient room left in the AG to + * complete a full tree split for an extent insert. If + * we are converting the middle part of an extent then + * we may need space for two tree splits. + * + * We are relying on the caller to make the correct block + * reservation for this operation to succeed. If the + * reservation amount is insufficient then we may fail a + * block allocation here and corrupt the filesystem. + */ + args.minleft = xfs_trans_get_block_res(args.tp); } else args.type = XFS_ALLOCTYPE_NEAR_BNO; - args.mod = args.minleft = args.alignment = args.total = args.isfl = + args.mod = args.alignment = args.total = args.isfl = args.userdata = args.minalignslop = 0; args.minlen = args.maxlen = args.prod = 1; args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 7edcde691d..67f22b2b44 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -889,6 +889,16 @@ xfs_iomap_write_unwritten( count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); count_fsb = (xfs_filblks_t)(count_fsb - offset_fsb); + /* + * Reserve enough blocks in this transaction for two complete extent + * btree splits. We may be converting the middle part of an unwritten + * extent and in this case we will insert two new extents in the btree + * each of which could cause a full split. + * + * This reservation amount will be used in the first call to + * xfs_bmbt_split() to select an AG with enough space to satisfy the + * rest of the operation. + */ resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0) << 1; do { -- 2.39.5