Skip to content

Commit 6a18765

Browse files
Christoph Hellwigcmaiolino
authored andcommitted
xfs: update the file system geometry after recoverying superblock buffers
Primary superblock buffers that change the file system geometry after a growfs operation can affect the operation of later CIL checkpoints that make use of the newly added space and allocation groups. Apply the changes to the in-memory structures as part of recovery pass 2, to ensure recovery works fine for such cases. In the future we should apply the logic to other updates such as features bits as well. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Carlos Maiolino <cem@kernel.org>
1 parent aa67ec6 commit 6a18765

File tree

2 files changed

+52
-8
lines changed

2 files changed

+52
-8
lines changed

fs/xfs/xfs_buf_item_recover.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include "xfs_inode.h"
2323
#include "xfs_dir2.h"
2424
#include "xfs_quota.h"
25+
#include "xfs_alloc.h"
26+
#include "xfs_ag.h"
27+
#include "xfs_sb.h"
2528

2629
/*
2730
* This is the number of entries in the l_buf_cancel_table used during
@@ -684,6 +687,49 @@ xlog_recover_do_inode_buffer(
684687
return 0;
685688
}
686689

690+
/*
691+
* Update the in-memory superblock and perag structures from the primary SB
692+
* buffer.
693+
*
694+
* This is required because transactions running after growfs may require the
695+
* updated values to be set in a previous fully commit transaction.
696+
*/
697+
static int
698+
xlog_recover_do_primary_sb_buffer(
699+
struct xfs_mount *mp,
700+
struct xlog_recover_item *item,
701+
struct xfs_buf *bp,
702+
struct xfs_buf_log_format *buf_f,
703+
xfs_lsn_t current_lsn)
704+
{
705+
struct xfs_dsb *dsb = bp->b_addr;
706+
xfs_agnumber_t orig_agcount = mp->m_sb.sb_agcount;
707+
int error;
708+
709+
xlog_recover_do_reg_buffer(mp, item, bp, buf_f, current_lsn);
710+
711+
/*
712+
* Update the in-core super block from the freshly recovered on-disk one.
713+
*/
714+
xfs_sb_from_disk(&mp->m_sb, dsb);
715+
716+
/*
717+
* Initialize the new perags, and also update various block and inode
718+
* allocator setting based off the number of AGs or total blocks.
719+
* Because of the latter this also needs to happen if the agcount did
720+
* not change.
721+
*/
722+
error = xfs_initialize_perag(mp, orig_agcount,
723+
mp->m_sb.sb_agcount, mp->m_sb.sb_dblocks,
724+
&mp->m_maxagi);
725+
if (error) {
726+
xfs_warn(mp, "Failed recovery per-ag init: %d", error);
727+
return error;
728+
}
729+
mp->m_alloc_set_aside = xfs_alloc_set_aside(mp);
730+
return 0;
731+
}
732+
687733
/*
688734
* V5 filesystems know the age of the buffer on disk being recovered. We can
689735
* have newer objects on disk than we are replaying, and so for these cases we
@@ -967,6 +1013,12 @@ xlog_recover_buf_commit_pass2(
9671013
dirty = xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
9681014
if (!dirty)
9691015
goto out_release;
1016+
} else if ((xfs_blft_from_flags(buf_f) & XFS_BLFT_SB_BUF) &&
1017+
xfs_buf_daddr(bp) == 0) {
1018+
error = xlog_recover_do_primary_sb_buffer(mp, item, bp, buf_f,
1019+
current_lsn);
1020+
if (error)
1021+
goto out_release;
9701022
} else {
9711023
xlog_recover_do_reg_buffer(mp, item, bp, buf_f, current_lsn);
9721024
}

fs/xfs/xfs_log_recover.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3346,7 +3346,6 @@ xlog_do_recover(
33463346
struct xfs_mount *mp = log->l_mp;
33473347
struct xfs_buf *bp = mp->m_sb_bp;
33483348
struct xfs_sb *sbp = &mp->m_sb;
3349-
xfs_agnumber_t orig_agcount = sbp->sb_agcount;
33503349
int error;
33513350

33523351
trace_xfs_log_recover(log, head_blk, tail_blk);
@@ -3394,13 +3393,6 @@ xlog_do_recover(
33943393
/* re-initialise in-core superblock and geometry structures */
33953394
mp->m_features |= xfs_sb_version_to_features(sbp);
33963395
xfs_reinit_percpu_counters(mp);
3397-
error = xfs_initialize_perag(mp, orig_agcount, sbp->sb_agcount,
3398-
sbp->sb_dblocks, &mp->m_maxagi);
3399-
if (error) {
3400-
xfs_warn(mp, "Failed post-recovery per-ag init: %d", error);
3401-
return error;
3402-
}
3403-
mp->m_alloc_set_aside = xfs_alloc_set_aside(mp);
34043396

34053397
/* Normal transactions can now occur */
34063398
clear_bit(XLOG_ACTIVE_RECOVERY, &log->l_opstate);

0 commit comments

Comments
 (0)