aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2017-02-02 02:55:55 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-02-04 03:47:11 -0500
commit6b81365b1e5795578c4aad59a37c15e958cdcdfe (patch)
treef58df243e62fd60e1171cd8e11b2b42e591a1875 /fs
parentc63f4d3aa09d0b8c36836a887d32cf20a974509f (diff)
xfs: adjust allocation length in xfs_alloc_space_available
commit 54fee133ad59c87ab01dd84ab3e9397134b32acb upstream. We must decide in xfs_alloc_fix_freelist if we can perform an allocation from a given AG is possible or not based on the available space, and should not fail the allocation past that point on a healthy file system. But currently we have two additional places that second-guess xfs_alloc_fix_freelist: xfs_alloc_ag_vextent tries to adjust the maxlen parameter to remove the reservation before doing the allocation (but ignores the various minium freespace requirements), and xfs_alloc_fix_minleft tries to fix up the allocated length after we've found an extent, but ignores the reservations and also doesn't take the AGFL into account (and thus fails allocations for not matching minlen in some cases). Remove all these later fixups and just correct the maxlen argument inside xfs_alloc_fix_freelist once we have the AGF buffer locked. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c81
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h2
2 files changed, 18 insertions, 65 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index fe925702c955..f2e7eb6e5243 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -362,36 +362,12 @@ xfs_alloc_fix_len(
362 return; 362 return;
363 ASSERT(rlen >= args->minlen && rlen <= args->maxlen); 363 ASSERT(rlen >= args->minlen && rlen <= args->maxlen);
364 ASSERT(rlen % args->prod == args->mod); 364 ASSERT(rlen % args->prod == args->mod);
365 ASSERT(args->pag->pagf_freeblks + args->pag->pagf_flcount >=
366 rlen + args->minleft);
365 args->len = rlen; 367 args->len = rlen;
366} 368}
367 369
368/* 370/*
369 * Fix up length if there is too little space left in the a.g.
370 * Return 1 if ok, 0 if too little, should give up.
371 */
372STATIC int
373xfs_alloc_fix_minleft(
374 xfs_alloc_arg_t *args) /* allocation argument structure */
375{
376 xfs_agf_t *agf; /* a.g. freelist header */
377 int diff; /* free space difference */
378
379 if (args->minleft == 0)
380 return 1;
381 agf = XFS_BUF_TO_AGF(args->agbp);
382 diff = be32_to_cpu(agf->agf_freeblks)
383 - args->len - args->minleft;
384 if (diff >= 0)
385 return 1;
386 args->len += diff; /* shrink the allocated space */
387 /* casts to (int) catch length underflows */
388 if ((int)args->len >= (int)args->minlen)
389 return 1;
390 args->agbno = NULLAGBLOCK;
391 return 0;
392}
393
394/*
395 * Update the two btrees, logically removing from freespace the extent 371 * Update the two btrees, logically removing from freespace the extent
396 * starting at rbno, rlen blocks. The extent is contained within the 372 * starting at rbno, rlen blocks. The extent is contained within the
397 * actual (current) free extent fbno for flen blocks. 373 * actual (current) free extent fbno for flen blocks.
@@ -686,8 +662,6 @@ xfs_alloc_ag_vextent(
686 xfs_alloc_arg_t *args) /* argument structure for allocation */ 662 xfs_alloc_arg_t *args) /* argument structure for allocation */
687{ 663{
688 int error=0; 664 int error=0;
689 xfs_extlen_t reservation;
690 xfs_extlen_t oldmax;
691 665
692 ASSERT(args->minlen > 0); 666 ASSERT(args->minlen > 0);
693 ASSERT(args->maxlen > 0); 667 ASSERT(args->maxlen > 0);
@@ -696,20 +670,6 @@ xfs_alloc_ag_vextent(
696 ASSERT(args->alignment > 0); 670 ASSERT(args->alignment > 0);
697 671
698 /* 672 /*
699 * Clamp maxlen to the amount of free space minus any reservations
700 * that have been made.
701 */
702 oldmax = args->maxlen;
703 reservation = xfs_ag_resv_needed(args->pag, args->resv);
704 if (args->maxlen > args->pag->pagf_freeblks - reservation)
705 args->maxlen = args->pag->pagf_freeblks - reservation;
706 if (args->maxlen == 0) {
707 args->agbno = NULLAGBLOCK;
708 args->maxlen = oldmax;
709 return 0;
710 }
711
712 /*
713 * Branch to correct routine based on the type. 673 * Branch to correct routine based on the type.
714 */ 674 */
715 args->wasfromfl = 0; 675 args->wasfromfl = 0;
@@ -728,8 +688,6 @@ xfs_alloc_ag_vextent(
728 /* NOTREACHED */ 688 /* NOTREACHED */
729 } 689 }
730 690
731 args->maxlen = oldmax;
732
733 if (error || args->agbno == NULLAGBLOCK) 691 if (error || args->agbno == NULLAGBLOCK)
734 return error; 692 return error;
735 693
@@ -838,9 +796,6 @@ xfs_alloc_ag_vextent_exact(
838 args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen) 796 args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen)
839 - args->agbno; 797 - args->agbno;
840 xfs_alloc_fix_len(args); 798 xfs_alloc_fix_len(args);
841 if (!xfs_alloc_fix_minleft(args))
842 goto not_found;
843
844 ASSERT(args->agbno + args->len <= tend); 799 ASSERT(args->agbno + args->len <= tend);
845 800
846 /* 801 /*
@@ -1146,12 +1101,7 @@ restart:
1146 XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0); 1101 XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
1147 ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); 1102 ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
1148 args->len = blen; 1103 args->len = blen;
1149 if (!xfs_alloc_fix_minleft(args)) { 1104
1150 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
1151 trace_xfs_alloc_near_nominleft(args);
1152 return 0;
1153 }
1154 blen = args->len;
1155 /* 1105 /*
1156 * We are allocating starting at bnew for blen blocks. 1106 * We are allocating starting at bnew for blen blocks.
1157 */ 1107 */
@@ -1343,12 +1293,6 @@ restart:
1343 */ 1293 */
1344 args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); 1294 args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
1345 xfs_alloc_fix_len(args); 1295 xfs_alloc_fix_len(args);
1346 if (!xfs_alloc_fix_minleft(args)) {
1347 trace_xfs_alloc_near_nominleft(args);
1348 xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR);
1349 xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
1350 return 0;
1351 }
1352 rlen = args->len; 1296 rlen = args->len;
1353 (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, 1297 (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment,
1354 args->datatype, ltbnoa, ltlena, &ltnew); 1298 args->datatype, ltbnoa, ltlena, &ltnew);
@@ -1550,8 +1494,6 @@ restart:
1550 } 1494 }
1551 xfs_alloc_fix_len(args); 1495 xfs_alloc_fix_len(args);
1552 1496
1553 if (!xfs_alloc_fix_minleft(args))
1554 goto out_nominleft;
1555 rlen = args->len; 1497 rlen = args->len;
1556 XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0); 1498 XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0);
1557 /* 1499 /*
@@ -2070,10 +2012,20 @@ xfs_alloc_space_available(
2070 2012
2071 /* do we have enough free space remaining for the allocation? */ 2013 /* do we have enough free space remaining for the allocation? */
2072 available = (int)(pag->pagf_freeblks + pag->pagf_flcount - 2014 available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
2073 reservation - min_free - args->total); 2015 reservation - min_free - args->minleft);
2074 if (available < (int)args->minleft || available <= 0) 2016 if (available < (int)args->total)
2075 return false; 2017 return false;
2076 2018
2019 /*
2020 * Clamp maxlen to the amount of free space available for the actual
2021 * extent allocation.
2022 */
2023 if (available < (int)args->maxlen && !(flags & XFS_ALLOC_FLAG_CHECK)) {
2024 args->maxlen = available;
2025 ASSERT(args->maxlen > 0);
2026 ASSERT(args->maxlen >= args->minlen);
2027 }
2028
2077 return true; 2029 return true;
2078} 2030}
2079 2031
@@ -2119,7 +2071,8 @@ xfs_alloc_fix_freelist(
2119 } 2071 }
2120 2072
2121 need = xfs_alloc_min_freelist(mp, pag); 2073 need = xfs_alloc_min_freelist(mp, pag);
2122 if (!xfs_alloc_space_available(args, need, flags)) 2074 if (!xfs_alloc_space_available(args, need, flags |
2075 XFS_ALLOC_FLAG_CHECK))
2123 goto out_agbp_relse; 2076 goto out_agbp_relse;
2124 2077
2125 /* 2078 /*
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index 7c404a6b0ae3..1d0f48a501a3 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -56,7 +56,7 @@ typedef unsigned int xfs_alloctype_t;
56#define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ 56#define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/
57#define XFS_ALLOC_FLAG_NORMAP 0x00000004 /* don't modify the rmapbt */ 57#define XFS_ALLOC_FLAG_NORMAP 0x00000004 /* don't modify the rmapbt */
58#define XFS_ALLOC_FLAG_NOSHRINK 0x00000008 /* don't shrink the freelist */ 58#define XFS_ALLOC_FLAG_NOSHRINK 0x00000008 /* don't shrink the freelist */
59 59#define XFS_ALLOC_FLAG_CHECK 0x00000010 /* test only, don't modify args */
60 60
61/* 61/*
62 * Argument structure for xfs_alloc routines. 62 * Argument structure for xfs_alloc routines.