Commit d5dbd1c9 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Greg Kroah-Hartman

xfs: try any AG when allocating the first btree block when reflinking

commit 2fcc319d 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: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent da617af8
...@@ -769,8 +769,8 @@ xfs_bmap_extents_to_btree( ...@@ -769,8 +769,8 @@ xfs_bmap_extents_to_btree(
args.type = XFS_ALLOCTYPE_START_BNO; args.type = XFS_ALLOCTYPE_START_BNO;
args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
} else if (dfops->dop_low) { } else if (dfops->dop_low) {
try_another_ag:
args.type = XFS_ALLOCTYPE_START_BNO; args.type = XFS_ALLOCTYPE_START_BNO;
try_another_ag:
args.fsbno = *firstblock; args.fsbno = *firstblock;
} else { } else {
args.type = XFS_ALLOCTYPE_NEAR_BNO; args.type = XFS_ALLOCTYPE_NEAR_BNO;
...@@ -796,13 +796,17 @@ xfs_bmap_extents_to_btree( ...@@ -796,13 +796,17 @@ xfs_bmap_extents_to_btree(
if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) &&
args.fsbno == NULLFSBLOCK && args.fsbno == NULLFSBLOCK &&
args.type == XFS_ALLOCTYPE_NEAR_BNO) { args.type == XFS_ALLOCTYPE_NEAR_BNO) {
dfops->dop_low = true; args.type = XFS_ALLOCTYPE_FIRST_AG;
goto try_another_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. * Allocation can't fail, the space was reserved.
*/ */
ASSERT(args.fsbno != NULLFSBLOCK);
ASSERT(*firstblock == NULLFSBLOCK || ASSERT(*firstblock == NULLFSBLOCK ||
args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock)); args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock));
*firstblock = cur->bc_private.b.firstblock = args.fsbno; *firstblock = cur->bc_private.b.firstblock = args.fsbno;
......
...@@ -453,8 +453,8 @@ xfs_bmbt_alloc_block( ...@@ -453,8 +453,8 @@ xfs_bmbt_alloc_block(
if (args.fsbno == NULLFSBLOCK) { if (args.fsbno == NULLFSBLOCK) {
args.fsbno = be64_to_cpu(start->l); args.fsbno = be64_to_cpu(start->l);
try_another_ag:
args.type = XFS_ALLOCTYPE_START_BNO; args.type = XFS_ALLOCTYPE_START_BNO;
try_another_ag:
/* /*
* Make sure there is sufficient room left in the AG to * Make sure there is sufficient room left in the AG to
* complete a full tree split for an extent insert. If * complete a full tree split for an extent insert. If
...@@ -494,8 +494,8 @@ xfs_bmbt_alloc_block( ...@@ -494,8 +494,8 @@ xfs_bmbt_alloc_block(
if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) &&
args.fsbno == NULLFSBLOCK && args.fsbno == NULLFSBLOCK &&
args.type == XFS_ALLOCTYPE_NEAR_BNO) { args.type == XFS_ALLOCTYPE_NEAR_BNO) {
cur->bc_private.b.dfops->dop_low = true;
args.fsbno = cur->bc_private.b.firstblock; args.fsbno = cur->bc_private.b.firstblock;
args.type = XFS_ALLOCTYPE_FIRST_AG;
goto try_another_ag; goto try_another_ag;
} }
...@@ -512,7 +512,7 @@ xfs_bmbt_alloc_block( ...@@ -512,7 +512,7 @@ xfs_bmbt_alloc_block(
goto error0; goto error0;
cur->bc_private.b.dfops->dop_low = true; 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); XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
*stat = 0; *stat = 0;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment