| From 2fcc319d2467a5f5b78f35f79fd6e22741a31b1e Mon Sep 17 00:00:00 2001 |
| From: Christoph Hellwig <hch@lst.de> |
| Date: Wed, 8 Mar 2017 10:38:53 -0800 |
| Subject: [PATCH] xfs: try any AG when allocating the first btree block when |
| reflinking |
| |
| commit 2fcc319d2467a5f5b78f35f79fd6e22741a31b1e upstream. |
| |
| When a reflink operation causes the bmap code to allocate a btree block |
| we're currently doing single-AG allocations due to having ->firstblock |
| set and then try any higher AG due a little reflink quirk we've put in |
| when adding the reflink code. But given that we do not have a minleft |
| reservation of any kind in this AG we can still not have any space in |
| the same or higher AG even if the file system has enough free space. |
| To fix this use a XFS_ALLOCTYPE_FIRST_AG allocation in this fall back |
| path instead. |
| |
| [And yes, we need to redo this properly instead of piling hacks over |
| hacks. I'm working on that, but it's not going to be a small series. |
| In the meantime this fixes the customer reported issue] |
| |
| Also add a warning for failing allocations to make it easier to debug. |
| |
| Signed-off-by: Christoph Hellwig <hch@lst.de> |
| Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> |
| Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> |
| |
| diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c |
| index bfa59a1a2d09..9bd104f32908 100644 |
| --- a/fs/xfs/libxfs/xfs_bmap.c |
| +++ b/fs/xfs/libxfs/xfs_bmap.c |
| @@ -763,8 +763,8 @@ xfs_bmap_extents_to_btree( |
| args.type = XFS_ALLOCTYPE_START_BNO; |
| args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); |
| } else if (dfops->dop_low) { |
| -try_another_ag: |
| args.type = XFS_ALLOCTYPE_START_BNO; |
| +try_another_ag: |
| args.fsbno = *firstblock; |
| } else { |
| args.type = XFS_ALLOCTYPE_NEAR_BNO; |
| @@ -790,13 +790,17 @@ try_another_ag: |
| if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && |
| args.fsbno == NULLFSBLOCK && |
| args.type == XFS_ALLOCTYPE_NEAR_BNO) { |
| - dfops->dop_low = true; |
| + args.type = XFS_ALLOCTYPE_FIRST_AG; |
| goto try_another_ag; |
| } |
| + if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) { |
| + xfs_iroot_realloc(ip, -1, whichfork); |
| + xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); |
| + return -ENOSPC; |
| + } |
| /* |
| * Allocation can't fail, the space was reserved. |
| */ |
| - ASSERT(args.fsbno != NULLFSBLOCK); |
| ASSERT(*firstblock == NULLFSBLOCK || |
| args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock)); |
| *firstblock = cur->bc_private.b.firstblock = args.fsbno; |
| diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c |
| index f93072b58a58..fd55db479385 100644 |
| --- a/fs/xfs/libxfs/xfs_bmap_btree.c |
| +++ b/fs/xfs/libxfs/xfs_bmap_btree.c |
| @@ -447,8 +447,8 @@ xfs_bmbt_alloc_block( |
| |
| if (args.fsbno == NULLFSBLOCK) { |
| args.fsbno = be64_to_cpu(start->l); |
| -try_another_ag: |
| args.type = XFS_ALLOCTYPE_START_BNO; |
| +try_another_ag: |
| /* |
| * Make sure there is sufficient room left in the AG to |
| * complete a full tree split for an extent insert. If |
| @@ -488,8 +488,8 @@ try_another_ag: |
| if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && |
| args.fsbno == NULLFSBLOCK && |
| args.type == XFS_ALLOCTYPE_NEAR_BNO) { |
| - cur->bc_private.b.dfops->dop_low = true; |
| args.fsbno = cur->bc_private.b.firstblock; |
| + args.type = XFS_ALLOCTYPE_FIRST_AG; |
| goto try_another_ag; |
| } |
| |
| @@ -506,7 +506,7 @@ try_another_ag: |
| goto error0; |
| cur->bc_private.b.dfops->dop_low = true; |
| } |
| - if (args.fsbno == NULLFSBLOCK) { |
| + if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) { |
| XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
| *stat = 0; |
| return 0; |
| -- |
| 2.12.0 |
| |