aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2017-01-09 10:39:01 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-01-12 05:39:44 -0500
commitb96e4e87d2b0fee921ceafa4f5ae1c90e9121db4 (patch)
tree551ab60a202153a24f1ed08c5ba762475a1f712f /fs
parentd9c7c9fa600acb0d587678cc71565316d11ec7ad (diff)
xfs: use the actual AG length when reserving blocks
commit 20e73b000bcded44a91b79429d8fa743247602ad upstream. We need to use the actual AG length when making per-AG reservations, since we could otherwise end up reserving more blocks out of the last AG than there are actual blocks. Complained-about-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/libxfs/xfs_ag_resv.c3
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.c9
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.h3
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c14
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.h3
-rw-r--r--fs/xfs/xfs_fsops.c14
6 files changed, 34 insertions, 12 deletions
diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c
index e5ebc3770460..d346d42c54d1 100644
--- a/fs/xfs/libxfs/xfs_ag_resv.c
+++ b/fs/xfs/libxfs/xfs_ag_resv.c
@@ -256,6 +256,9 @@ xfs_ag_resv_init(
256 goto out; 256 goto out;
257 } 257 }
258 258
259 ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved +
260 xfs_perag_resv(pag, XFS_AG_RESV_AGFL)->ar_reserved <=
261 pag->pagf_freeblks + pag->pagf_flcount);
259out: 262out:
260 return error; 263 return error;
261} 264}
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c
index 453bb2757ec2..2ba216966002 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.c
+++ b/fs/xfs/libxfs/xfs_refcount_btree.c
@@ -408,13 +408,14 @@ xfs_refcountbt_calc_size(
408 */ 408 */
409xfs_extlen_t 409xfs_extlen_t
410xfs_refcountbt_max_size( 410xfs_refcountbt_max_size(
411 struct xfs_mount *mp) 411 struct xfs_mount *mp,
412 xfs_agblock_t agblocks)
412{ 413{
413 /* Bail out if we're uninitialized, which can happen in mkfs. */ 414 /* Bail out if we're uninitialized, which can happen in mkfs. */
414 if (mp->m_refc_mxr[0] == 0) 415 if (mp->m_refc_mxr[0] == 0)
415 return 0; 416 return 0;
416 417
417 return xfs_refcountbt_calc_size(mp, mp->m_sb.sb_agblocks); 418 return xfs_refcountbt_calc_size(mp, agblocks);
418} 419}
419 420
420/* 421/*
@@ -429,22 +430,24 @@ xfs_refcountbt_calc_reserves(
429{ 430{
430 struct xfs_buf *agbp; 431 struct xfs_buf *agbp;
431 struct xfs_agf *agf; 432 struct xfs_agf *agf;
433 xfs_agblock_t agblocks;
432 xfs_extlen_t tree_len; 434 xfs_extlen_t tree_len;
433 int error; 435 int error;
434 436
435 if (!xfs_sb_version_hasreflink(&mp->m_sb)) 437 if (!xfs_sb_version_hasreflink(&mp->m_sb))
436 return 0; 438 return 0;
437 439
438 *ask += xfs_refcountbt_max_size(mp);
439 440
440 error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); 441 error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
441 if (error) 442 if (error)
442 return error; 443 return error;
443 444
444 agf = XFS_BUF_TO_AGF(agbp); 445 agf = XFS_BUF_TO_AGF(agbp);
446 agblocks = be32_to_cpu(agf->agf_length);
445 tree_len = be32_to_cpu(agf->agf_refcount_blocks); 447 tree_len = be32_to_cpu(agf->agf_refcount_blocks);
446 xfs_buf_relse(agbp); 448 xfs_buf_relse(agbp);
447 449
450 *ask += xfs_refcountbt_max_size(mp, agblocks);
448 *used += tree_len; 451 *used += tree_len;
449 452
450 return error; 453 return error;
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.h b/fs/xfs/libxfs/xfs_refcount_btree.h
index 3be7768bd51a..9db008b955b7 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.h
+++ b/fs/xfs/libxfs/xfs_refcount_btree.h
@@ -66,7 +66,8 @@ extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp);
66 66
67extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp, 67extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp,
68 unsigned long long len); 68 unsigned long long len);
69extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp); 69extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp,
70 xfs_agblock_t agblocks);
70 71
71extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp, 72extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp,
72 xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); 73 xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used);
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
index 83e672ff7577..33a28efc3085 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rmap_btree.c
@@ -549,13 +549,14 @@ xfs_rmapbt_calc_size(
549 */ 549 */
550xfs_extlen_t 550xfs_extlen_t
551xfs_rmapbt_max_size( 551xfs_rmapbt_max_size(
552 struct xfs_mount *mp) 552 struct xfs_mount *mp,
553 xfs_agblock_t agblocks)
553{ 554{
554 /* Bail out if we're uninitialized, which can happen in mkfs. */ 555 /* Bail out if we're uninitialized, which can happen in mkfs. */
555 if (mp->m_rmap_mxr[0] == 0) 556 if (mp->m_rmap_mxr[0] == 0)
556 return 0; 557 return 0;
557 558
558 return xfs_rmapbt_calc_size(mp, mp->m_sb.sb_agblocks); 559 return xfs_rmapbt_calc_size(mp, agblocks);
559} 560}
560 561
561/* 562/*
@@ -570,25 +571,24 @@ xfs_rmapbt_calc_reserves(
570{ 571{
571 struct xfs_buf *agbp; 572 struct xfs_buf *agbp;
572 struct xfs_agf *agf; 573 struct xfs_agf *agf;
573 xfs_extlen_t pool_len; 574 xfs_agblock_t agblocks;
574 xfs_extlen_t tree_len; 575 xfs_extlen_t tree_len;
575 int error; 576 int error;
576 577
577 if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) 578 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
578 return 0; 579 return 0;
579 580
580 /* Reserve 1% of the AG or enough for 1 block per record. */
581 pool_len = max(mp->m_sb.sb_agblocks / 100, xfs_rmapbt_max_size(mp));
582 *ask += pool_len;
583
584 error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); 581 error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
585 if (error) 582 if (error)
586 return error; 583 return error;
587 584
588 agf = XFS_BUF_TO_AGF(agbp); 585 agf = XFS_BUF_TO_AGF(agbp);
586 agblocks = be32_to_cpu(agf->agf_length);
589 tree_len = be32_to_cpu(agf->agf_rmap_blocks); 587 tree_len = be32_to_cpu(agf->agf_rmap_blocks);
590 xfs_buf_relse(agbp); 588 xfs_buf_relse(agbp);
591 589
590 /* Reserve 1% of the AG or enough for 1 block per record. */
591 *ask += max(agblocks / 100, xfs_rmapbt_max_size(mp, agblocks));
592 *used += tree_len; 592 *used += tree_len;
593 593
594 return error; 594 return error;
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h
index 2a9ac472fb15..19c08e933049 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.h
+++ b/fs/xfs/libxfs/xfs_rmap_btree.h
@@ -60,7 +60,8 @@ extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp);
60 60
61extern xfs_extlen_t xfs_rmapbt_calc_size(struct xfs_mount *mp, 61extern xfs_extlen_t xfs_rmapbt_calc_size(struct xfs_mount *mp,
62 unsigned long long len); 62 unsigned long long len);
63extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp); 63extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp,
64 xfs_agblock_t agblocks);
64 65
65extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, 66extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp,
66 xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); 67 xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used);
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 93d12fa2670d..242e8091296d 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -631,6 +631,20 @@ xfs_growfs_data_private(
631 xfs_set_low_space_thresholds(mp); 631 xfs_set_low_space_thresholds(mp);
632 mp->m_alloc_set_aside = xfs_alloc_set_aside(mp); 632 mp->m_alloc_set_aside = xfs_alloc_set_aside(mp);
633 633
634 /*
635 * If we expanded the last AG, free the per-AG reservation
636 * so we can reinitialize it with the new size.
637 */
638 if (new) {
639 struct xfs_perag *pag;
640
641 pag = xfs_perag_get(mp, agno);
642 error = xfs_ag_resv_free(pag);
643 xfs_perag_put(pag);
644 if (error)
645 goto out;
646 }
647
634 /* Reserve AG metadata blocks. */ 648 /* Reserve AG metadata blocks. */
635 error = xfs_fs_reserve_ag_blocks(mp); 649 error = xfs_fs_reserve_ag_blocks(mp);
636 if (error && error != -ENOSPC) 650 if (error && error != -ENOSPC)