@@ -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);
+}
@@ -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 */
@@ -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.
@@ -1100,6 +1101,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);
}
/*
@@ -1216,6 +1219,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);
@@ -1225,6 +1229,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)
@@ -1233,7 +1242,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;
}
@@ -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:
@@ -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);
}
/*
@@ -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 *);
@@ -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