aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2017-03-08 13:38:53 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-08 03:30:32 -0400
commitd5dbd1c9592062ef170fb895f7aa483f781e63f6 (patch)
tree0297068892f70b338cf987d1c9b2003e3c6f1174
parentda617af8f0c6fa9cd2694440529f5edf99c0c6d1 (diff)
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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c10
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c6
2 files changed, 10 insertions, 6 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index ec93395eccdc..5a508b011e27 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -769,8 +769,8 @@ xfs_bmap_extents_to_btree(
769 args.type = XFS_ALLOCTYPE_START_BNO; 769 args.type = XFS_ALLOCTYPE_START_BNO;
770 args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); 770 args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
771 } else if (dfops->dop_low) { 771 } else if (dfops->dop_low) {
772try_another_ag:
773 args.type = XFS_ALLOCTYPE_START_BNO; 772 args.type = XFS_ALLOCTYPE_START_BNO;
773try_another_ag:
774 args.fsbno = *firstblock; 774 args.fsbno = *firstblock;
775 } else { 775 } else {
776 args.type = XFS_ALLOCTYPE_NEAR_BNO; 776 args.type = XFS_ALLOCTYPE_NEAR_BNO;
@@ -796,13 +796,17 @@ try_another_ag:
796 if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && 796 if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) &&
797 args.fsbno == NULLFSBLOCK && 797 args.fsbno == NULLFSBLOCK &&
798 args.type == XFS_ALLOCTYPE_NEAR_BNO) { 798 args.type == XFS_ALLOCTYPE_NEAR_BNO) {
799 dfops->dop_low = true; 799 args.type = XFS_ALLOCTYPE_FIRST_AG;
800 goto try_another_ag; 800 goto try_another_ag;
801 } 801 }
802 if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
803 xfs_iroot_realloc(ip, -1, whichfork);
804 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
805 return -ENOSPC;
806 }
802 /* 807 /*
803 * Allocation can't fail, the space was reserved. 808 * Allocation can't fail, the space was reserved.
804 */ 809 */
805 ASSERT(args.fsbno != NULLFSBLOCK);
806 ASSERT(*firstblock == NULLFSBLOCK || 810 ASSERT(*firstblock == NULLFSBLOCK ||
807 args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock)); 811 args.agno >= XFS_FSB_TO_AGNO(mp, *firstblock));
808 *firstblock = cur->bc_private.b.firstblock = args.fsbno; 812 *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 f76c1693ff01..5c3918678bb6 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -453,8 +453,8 @@ xfs_bmbt_alloc_block(
453 453
454 if (args.fsbno == NULLFSBLOCK) { 454 if (args.fsbno == NULLFSBLOCK) {
455 args.fsbno = be64_to_cpu(start->l); 455 args.fsbno = be64_to_cpu(start->l);
456try_another_ag:
457 args.type = XFS_ALLOCTYPE_START_BNO; 456 args.type = XFS_ALLOCTYPE_START_BNO;
457try_another_ag:
458 /* 458 /*
459 * Make sure there is sufficient room left in the AG to 459 * Make sure there is sufficient room left in the AG to
460 * complete a full tree split for an extent insert. If 460 * complete a full tree split for an extent insert. If
@@ -494,8 +494,8 @@ try_another_ag:
494 if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && 494 if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) &&
495 args.fsbno == NULLFSBLOCK && 495 args.fsbno == NULLFSBLOCK &&
496 args.type == XFS_ALLOCTYPE_NEAR_BNO) { 496 args.type == XFS_ALLOCTYPE_NEAR_BNO) {
497 cur->bc_private.b.dfops->dop_low = true;
498 args.fsbno = cur->bc_private.b.firstblock; 497 args.fsbno = cur->bc_private.b.firstblock;
498 args.type = XFS_ALLOCTYPE_FIRST_AG;
499 goto try_another_ag; 499 goto try_another_ag;
500 } 500 }
501 501
@@ -512,7 +512,7 @@ try_another_ag:
512 goto error0; 512 goto error0;
513 cur->bc_private.b.dfops->dop_low = true; 513 cur->bc_private.b.dfops->dop_low = true;
514 } 514 }
515 if (args.fsbno == NULLFSBLOCK) { 515 if (WARN_ON_ONCE(args.fsbno == NULLFSBLOCK)) {
516 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 516 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
517 *stat = 0; 517 *stat = 0;
518 return 0; 518 return 0;