summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2022-08-15 11:57:02 -0700
committerDarrick J. Wong <djwong@kernel.org>2022-11-09 19:07:57 -0800
commitb2cb1ceb25713528dc54680f3ca693f1df4f8a51 (patch)
tree50a9f319e51decf4011251a9051995afc8bfeaf2
parent658d90c197b4e164d7854a7920b5d0f11a613ed5 (diff)
xfs: update primary realtime super every time we update the primary fs super
Every time we update parts of the primary filesystem superblock that are echoed in the primary rt super, we should update that primary realtime super. Avoid an ondisk log format change by using ordered buffers to write the primary rt super. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/libxfs/xfs_rtgroup.c74
-rw-r--r--fs/xfs/libxfs/xfs_rtgroup.h6
-rw-r--r--fs/xfs/libxfs/xfs_sb.c13
-rw-r--r--fs/xfs/xfs_buf_item_recover.c18
-rw-r--r--fs/xfs/xfs_trans.c10
-rw-r--r--fs/xfs/xfs_trans.h1
-rw-r--r--fs/xfs/xfs_trans_buf.c25
7 files changed, 142 insertions, 5 deletions
diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c
index edbc427725c3..e9655e699f4f 100644
--- a/fs/xfs/libxfs/xfs_rtgroup.c
+++ b/fs/xfs/libxfs/xfs_rtgroup.c
@@ -308,3 +308,77 @@ const struct xfs_buf_ops xfs_rtsb_buf_ops = {
.verify_write = xfs_rtsb_write_verify,
.verify_struct = xfs_rtsb_verify,
};
+
+/* Update a realtime superblock from the primary fs super */
+void
+xfs_rtgroup_update_super(
+ struct xfs_buf *rtsb_bp,
+ const struct xfs_buf *sb_bp)
+{
+ const struct xfs_dsb *dsb = sb_bp->b_addr;
+ struct xfs_rtsb *rsb = rtsb_bp->b_addr;
+ const uuid_t *meta_uuid;
+
+ rsb->rsb_magicnum = cpu_to_be32(XFS_RTSB_MAGIC);
+ rsb->rsb_blocksize = dsb->sb_blocksize;
+ rsb->rsb_rblocks = dsb->sb_rblocks;
+
+ rsb->rsb_rextents = dsb->sb_rextents;
+ rsb->rsb_lsn = 0;
+
+ memcpy(&rsb->rsb_uuid, &dsb->sb_uuid, sizeof(rsb->rsb_uuid));
+
+ rsb->rsb_rgcount = dsb->sb_rgcount;
+ memcpy(&rsb->rsb_fname, &dsb->sb_fname, XFSLABEL_MAX);
+
+ rsb->rsb_rextsize = dsb->sb_rextsize;
+ rsb->rsb_rbmblocks = dsb->sb_rbmblocks;
+
+ rsb->rsb_rgblocks = dsb->sb_rgblocks;
+ rsb->rsb_blocklog = dsb->sb_blocklog;
+ rsb->rsb_sectlog = dsb->sb_sectlog;
+ rsb->rsb_rextslog = dsb->sb_rextslog;
+ rsb->rsb_pad = 0;
+ rsb->rsb_pad2 = 0;
+
+ /*
+ * The metadata uuid is the fs uuid if the metauuid feature is not
+ * enabled.
+ */
+ if (dsb->sb_features_incompat &
+ cpu_to_be32(XFS_SB_FEAT_INCOMPAT_META_UUID))
+ meta_uuid = &dsb->sb_meta_uuid;
+ else
+ meta_uuid = &dsb->sb_uuid;
+ memcpy(&rsb->rsb_meta_uuid, meta_uuid, sizeof(rsb->rsb_meta_uuid));
+}
+
+/*
+ * Update the primary realtime superblock from a filesystem superblock and
+ * log it to the given transaction.
+ */
+void
+xfs_rtgroup_log_super(
+ struct xfs_trans *tp,
+ const struct xfs_buf *sb_bp)
+{
+ struct xfs_buf *rtsb_bp;
+
+ if (!xfs_has_rtgroups(tp->t_mountp))
+ return;
+
+ rtsb_bp = xfs_trans_getrtsb(tp);
+ if (!rtsb_bp) {
+ /*
+ * It's possible for the rtgroups feature to be enabled but
+ * there is no incore rt superblock buffer if the rt geometry
+ * was specified at mkfs time but the rt section has not yet
+ * been attached. In this case, rblocks must be zero.
+ */
+ ASSERT(tp->t_mountp->m_sb.sb_rblocks == 0);
+ return;
+ }
+
+ xfs_rtgroup_update_super(rtsb_bp, sb_bp);
+ xfs_trans_ordered_buf(tp, rtsb_bp);
+}
diff --git a/fs/xfs/libxfs/xfs_rtgroup.h b/fs/xfs/libxfs/xfs_rtgroup.h
index ff9b01d8c501..c6db6b0d2ae5 100644
--- a/fs/xfs/libxfs/xfs_rtgroup.h
+++ b/fs/xfs/libxfs/xfs_rtgroup.h
@@ -197,8 +197,14 @@ xfs_daddr_to_rgbno(
#ifdef CONFIG_XFS_RT
xfs_rgblock_t xfs_rtgroup_block_count(struct xfs_mount *mp,
xfs_rgnumber_t rgno);
+
+void xfs_rtgroup_update_super(struct xfs_buf *rtsb_bp,
+ const struct xfs_buf *sb_bp);
+void xfs_rtgroup_log_super(struct xfs_trans *tp, const struct xfs_buf *sb_bp);
#else
# define xfs_rtgroup_block_count(mp, rgno) (0)
+# define xfs_rtgroup_update_super(bp, sb_bp) ((void)0)
+# define xfs_rtgroup_log_super(tp, sb_bp) ((void)0)
#endif /* CONFIG_XFS_RT */
#endif /* __LIBXFS_RTGROUP_H */
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index bdb48a1d47bc..599a5829ccd2 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -26,6 +26,7 @@
#include "xfs_health.h"
#include "xfs_ag.h"
#include "xfs_swapext.h"
+#include "xfs_rtgroup.h"
/*
* Physical superblock buffer manipulations. Shared with libxfs in userspace.
@@ -1098,6 +1099,8 @@ xfs_log_sb(
xfs_sb_to_disk(bp->b_addr, &mp->m_sb);
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb) - 1);
+
+ xfs_rtgroup_log_super(tp, bp);
}
/*
@@ -1214,6 +1217,7 @@ xfs_sync_sb_buf(
{
struct xfs_trans *tp;
struct xfs_buf *bp;
+ struct xfs_buf *rtsb_bp = NULL;
int error;
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp);
@@ -1223,6 +1227,11 @@ xfs_sync_sb_buf(
bp = xfs_trans_getsb(tp);
xfs_log_sb(tp);
xfs_trans_bhold(tp, bp);
+ if (xfs_has_rtgroups(mp)) {
+ rtsb_bp = xfs_trans_getrtsb(tp);
+ if (rtsb_bp)
+ xfs_trans_bhold(tp, rtsb_bp);
+ }
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp);
if (error)
@@ -1231,7 +1240,11 @@ xfs_sync_sb_buf(
* write out the sb buffer to get the changes to disk
*/
error = xfs_bwrite(bp);
+ if (!error && rtsb_bp)
+ error = xfs_bwrite(rtsb_bp);
out:
+ if (rtsb_bp)
+ xfs_buf_relse(rtsb_bp);
xfs_buf_relse(bp);
return error;
}
diff --git a/fs/xfs/xfs_buf_item_recover.c b/fs/xfs/xfs_buf_item_recover.c
index ffa94102094d..6587d18b21c3 100644
--- a/fs/xfs/xfs_buf_item_recover.c
+++ b/fs/xfs/xfs_buf_item_recover.c
@@ -22,6 +22,7 @@
#include "xfs_inode.h"
#include "xfs_dir2.h"
#include "xfs_quota.h"
+#include "xfs_rtgroup.h"
/*
* This is the number of entries in the l_buf_cancel_table used during
@@ -985,6 +986,23 @@ xlog_recover_buf_commit_pass2(
ASSERT(bp->b_mount == mp);
bp->b_flags |= _XBF_LOGRECOVERY;
xfs_buf_delwri_queue(bp, buffer_list);
+
+ /*
+ * Update the primary rt super if we just recovered the primary
+ * fs super.
+ */
+ if (xfs_has_rtgroups(mp) && bp->b_ops == &xfs_sb_buf_ops) {
+ struct xfs_buf *rtsb_bp = mp->m_rtsb_bp;
+
+ if (rtsb_bp) {
+ xfs_buf_lock(rtsb_bp);
+ xfs_buf_hold(rtsb_bp);
+ xfs_rtgroup_update_super(rtsb_bp, bp);
+ rtsb_bp->b_flags |= _XBF_LOGRECOVERY;
+ xfs_buf_delwri_queue(rtsb_bp, buffer_list);
+ xfs_buf_relse(rtsb_bp);
+ }
+ }
}
out_release:
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index f39c5daeef86..979aba1b2fc8 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -25,6 +25,7 @@
#include "xfs_dquot.h"
#include "xfs_icache.h"
#include "xfs_rtbitmap.h"
+#include "xfs_rtgroup.h"
struct kmem_cache *xfs_trans_cache;
@@ -531,6 +532,7 @@ xfs_trans_apply_sb_deltas(
{
struct xfs_dsb *sbp;
struct xfs_buf *bp;
+ bool update_rtsb = false;
int whole = 0;
bp = xfs_trans_getsb(tp);
@@ -591,22 +593,27 @@ xfs_trans_apply_sb_deltas(
if (tp->t_rextsize_delta) {
be32_add_cpu(&sbp->sb_rextsize, tp->t_rextsize_delta);
whole = 1;
+ update_rtsb = true;
}
if (tp->t_rbmblocks_delta) {
be32_add_cpu(&sbp->sb_rbmblocks, tp->t_rbmblocks_delta);
whole = 1;
+ update_rtsb = true;
}
if (tp->t_rblocks_delta) {
be64_add_cpu(&sbp->sb_rblocks, tp->t_rblocks_delta);
whole = 1;
+ update_rtsb = true;
}
if (tp->t_rextents_delta) {
be64_add_cpu(&sbp->sb_rextents, tp->t_rextents_delta);
whole = 1;
+ update_rtsb = true;
}
if (tp->t_rextslog_delta) {
sbp->sb_rextslog += tp->t_rextslog_delta;
whole = 1;
+ update_rtsb = true;
}
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);
@@ -623,6 +630,9 @@ xfs_trans_apply_sb_deltas(
xfs_trans_log_buf(tp, bp, offsetof(struct xfs_dsb, sb_icount),
offsetof(struct xfs_dsb, sb_frextents) +
sizeof(sbp->sb_frextents) - 1);
+
+ if (update_rtsb)
+ xfs_rtgroup_log_super(tp, bp);
}
/*
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 0a9ec6929bbc..37cde68f3a31 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -216,6 +216,7 @@ xfs_trans_read_buf(
}
struct xfs_buf *xfs_trans_getsb(struct xfs_trans *);
+struct xfs_buf *xfs_trans_getrtsb(struct xfs_trans *tp);
void xfs_trans_brelse(xfs_trans_t *, struct xfs_buf *);
void xfs_trans_bjoin(xfs_trans_t *, struct xfs_buf *);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index e28ab74af4f0..8e886ecfd69a 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -168,12 +168,11 @@ xfs_trans_get_buf_map(
/*
* Get and lock the superblock buffer for the given transaction.
*/
-struct xfs_buf *
-xfs_trans_getsb(
- struct xfs_trans *tp)
+static struct xfs_buf *
+__xfs_trans_getsb(
+ struct xfs_trans *tp,
+ struct xfs_buf *bp)
{
- struct xfs_buf *bp = tp->t_mountp->m_sb_bp;
-
/*
* Just increment the lock recursion count if the buffer is already
* attached to this transaction.
@@ -197,6 +196,22 @@ xfs_trans_getsb(
return bp;
}
+struct xfs_buf *
+xfs_trans_getsb(
+ struct xfs_trans *tp)
+{
+ return __xfs_trans_getsb(tp, tp->t_mountp->m_sb_bp);
+}
+
+struct xfs_buf *
+xfs_trans_getrtsb(
+ struct xfs_trans *tp)
+{
+ if (!tp->t_mountp->m_rtsb_bp)
+ return NULL;
+ return __xfs_trans_getsb(tp, tp->t_mountp->m_rtsb_bp);
+}
+
/*
* Get and lock the buffer for the caller if it is not already
* locked within the given transaction. If it has not yet been