]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: update realtime super every time we update the primary fs super
authorDarrick J. Wong <djwong@kernel.org>
Mon, 25 Nov 2024 21:14:21 +0000 (13:14 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 24 Dec 2024 02:01:29 +0000 (18:01 -0800)
Source kernel commit: 76d3be00df91a56f7c05142ed500f8f8544d5457

Every time we update parts of the primary filesystem superblock that are
echoed in the rt superblock, we must update the rt super.  Avoid
changing the log to support logging to the rt device by using ordered
buffers.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
include/xfs_trans.h
libxfs/libxfs_api_defs.h
libxfs/libxfs_io.h
libxfs/rdwr.c
libxfs/trans.c
libxfs/xfs_rtgroup.c
libxfs/xfs_rtgroup.h
libxfs/xfs_sb.c
libxfs/xfs_sb.h

index d508f8947a301cbc675fc38a2f8ef88d573210a8..248064019a0ab567d0c0ba3022ed10f043d2689b 100644 (file)
@@ -108,6 +108,7 @@ int libxfs_trans_reserve_more(struct xfs_trans *tp, uint blocks,
 void xfs_defer_cancel(struct xfs_trans *);
 
 struct xfs_buf *libxfs_trans_getsb(struct xfs_trans *);
+struct xfs_buf *libxfs_trans_getrtsb(struct xfs_trans *tp);
 
 void   libxfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint);
 void   libxfs_trans_log_inode (struct xfs_trans *, struct xfs_inode *,
index c869a4b0a46551b9222831761d9bb66d39b80089..50da547f8f21d48bece0bb07dfb7564a3623836e 100644 (file)
 #define xfs_trans_dirty_buf            libxfs_trans_dirty_buf
 #define xfs_trans_get_buf              libxfs_trans_get_buf
 #define xfs_trans_get_buf_map          libxfs_trans_get_buf_map
+#define xfs_trans_getrtsb              libxfs_trans_getrtsb
 #define xfs_trans_getsb                        libxfs_trans_getsb
 #define xfs_trans_ichgtime             libxfs_trans_ichgtime
 #define xfs_trans_ijoin                        libxfs_trans_ijoin
index 82d86f1d1b37bf5e29251407f3cc4ddc18cf15a3..99372eb6d3d13cf0839742cac966fd3c436b2d56 100644 (file)
@@ -208,6 +208,7 @@ libxfs_buf_read(
 
 int libxfs_readbuf_verify(struct xfs_buf *bp, const struct xfs_buf_ops *ops);
 struct xfs_buf *libxfs_getsb(struct xfs_mount *mp);
+struct xfs_buf *libxfs_getrtsb(struct xfs_mount *mp);
 extern void    libxfs_bcache_purge(struct xfs_mount *mp);
 extern void    libxfs_bcache_free(void);
 extern void    libxfs_bcache_flush(struct xfs_mount *mp);
index 7d4d93e4f094e60af619db32867a679377a437f7..35be785c435a974f036ec42615b6c09174ebe7f5 100644 (file)
@@ -165,6 +165,23 @@ libxfs_getsb(
        return bp;
 }
 
+struct xfs_buf *
+libxfs_getrtsb(
+       struct xfs_mount        *mp)
+{
+       struct xfs_buf          *bp;
+       int                     error;
+
+       if (!mp->m_rtdev_targp->bt_bdev)
+               return NULL;
+
+       error = libxfs_buf_read_uncached(mp->m_rtdev_targp, XFS_RTSB_DADDR,
+                       XFS_FSB_TO_BB(mp, 1), 0, &bp, &xfs_rtsb_buf_ops);
+       if (error)
+               return NULL;
+       return bp;
+}
+
 struct kmem_cache                      *xfs_buf_cache;
 
 static struct cache_mru                xfs_buf_freelist =
index 72f2659105371674f49430a43e4d9c91ca9d91f9..01834eff4b77cae1376d2904750dadd24ff956bf 100644 (file)
@@ -512,6 +512,35 @@ libxfs_trans_getsb(
        return bp;
 }
 
+struct xfs_buf *
+libxfs_trans_getrtsb(
+       struct xfs_trans        *tp)
+{
+       struct xfs_mount        *mp = tp->t_mountp;
+       struct xfs_buf          *bp;
+       struct xfs_buf_log_item *bip;
+       int                     len = XFS_FSS_TO_BB(mp, 1);
+       DEFINE_SINGLE_BUF_MAP(map, XFS_SB_DADDR, len);
+
+       bp = xfs_trans_buf_item_match(tp, mp->m_rtdev, &map, 1);
+       if (bp != NULL) {
+               ASSERT(bp->b_transp == tp);
+               bip = bp->b_log_item;
+               ASSERT(bip != NULL);
+               bip->bli_recur++;
+               trace_xfs_trans_getsb_recur(bip);
+               return bp;
+       }
+
+       bp = libxfs_getrtsb(mp);
+       if (bp == NULL)
+               return NULL;
+
+       _libxfs_trans_bjoin(tp, bp, 1);
+       trace_xfs_trans_getsb(bp->b_log_item);
+       return bp;
+}
+
 int
 libxfs_trans_read_buf_map(
        struct xfs_mount        *mp,
index e294a295b3d0d82d2ee46060cf53547de694d0fb..6eabc66099dc509672444c355e2354f53134ec17 100644 (file)
@@ -561,3 +561,63 @@ const struct xfs_buf_ops xfs_rtsb_buf_ops = {
        .verify_write   = xfs_rtsb_write_verify,
        .verify_struct  = xfs_rtsb_verify_all,
 };
+
+/* Update a realtime superblock from the primary fs super */
+void
+xfs_update_rtsb(
+       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_pad = 0;
+       memcpy(&rsb->rsb_fname, &dsb->sb_fname, XFSLABEL_MAX);
+
+       memcpy(&rsb->rsb_uuid, &dsb->sb_uuid, sizeof(rsb->rsb_uuid));
+
+       /*
+        * 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 realtime superblock from a filesystem superblock and log it to
+ * the given transaction.
+ */
+struct xfs_buf *
+xfs_log_rtsb(
+       struct xfs_trans        *tp,
+       const struct xfs_buf    *sb_bp)
+{
+       struct xfs_buf          *rtsb_bp;
+
+       if (!xfs_has_rtsb(tp->t_mountp))
+               return NULL;
+
+       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 NULL;
+       }
+
+       xfs_update_rtsb(rtsb_bp, sb_bp);
+       xfs_trans_ordered_buf(tp, rtsb_bp);
+       return rtsb_bp;
+}
index 6ccf31bb6bc7a7a643bb6ea05cd7403b0d72c013..e7679fafff8ce782fea19e6da2d584db3ed0ffec 100644 (file)
@@ -251,6 +251,11 @@ static inline const char *xfs_rtginode_path(xfs_rgnumber_t rgno,
 {
        return kasprintf(GFP_KERNEL, "%u.%s", rgno, xfs_rtginode_name(type));
 }
+
+void xfs_update_rtsb(struct xfs_buf *rtsb_bp,
+               const struct xfs_buf *sb_bp);
+struct xfs_buf *xfs_log_rtsb(struct xfs_trans *tp,
+               const struct xfs_buf *sb_bp);
 #else
 static inline void xfs_free_rtgroups(struct xfs_mount *mp,
                xfs_rgnumber_t first_rgno, xfs_rgnumber_t end_rgno)
@@ -269,6 +274,8 @@ static inline int xfs_initialize_rtgroups(struct xfs_mount *mp,
 # define xfs_rtgroup_lock(rtg, gf)             ((void)0)
 # define xfs_rtgroup_unlock(rtg, gf)           ((void)0)
 # define xfs_rtgroup_trans_join(tp, rtg, gf)   ((void)0)
+# define xfs_update_rtsb(bp, sb_bp)    ((void)0)
+# define xfs_log_rtsb(tp, sb_bp)       (NULL)
 #endif /* CONFIG_XFS_RT */
 
 #endif /* __LIBXFS_RTGROUP_H */
index 3c80413b67f6ec85f6a442ae6730ccc9d65081e6..96b0a73682f435ebe738e2ba17150fa8be7db5d3 100644 (file)
@@ -24,6 +24,7 @@
 #include "xfs_health.h"
 #include "xfs_ag.h"
 #include "xfs_rtbitmap.h"
+#include "xfs_rtgroup.h"
 
 /*
  * Physical superblock buffer manipulations. Shared with libxfs in userspace.
@@ -1287,10 +1288,12 @@ xfs_update_secondary_sbs(
  */
 int
 xfs_sync_sb_buf(
-       struct xfs_mount        *mp)
+       struct xfs_mount        *mp,
+       bool                    update_rtsb)
 {
        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);
@@ -1300,6 +1303,11 @@ xfs_sync_sb_buf(
        bp = xfs_trans_getsb(tp);
        xfs_log_sb(tp);
        xfs_trans_bhold(tp, bp);
+       if (update_rtsb) {
+               rtsb_bp = xfs_log_rtsb(tp, bp);
+               if (rtsb_bp)
+                       xfs_trans_bhold(tp, rtsb_bp);
+       }
        xfs_trans_set_sync(tp);
        error = xfs_trans_commit(tp);
        if (error)
@@ -1308,7 +1316,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;
 }
index 885c837559914d7257d4b76af427f67f82e1ef4a..999dcfccdaf9602912858276d77db6dbe34ebc3c 100644 (file)
@@ -15,7 +15,7 @@ struct xfs_perag;
 
 extern void    xfs_log_sb(struct xfs_trans *tp);
 extern int     xfs_sync_sb(struct xfs_mount *mp, bool wait);
-extern int     xfs_sync_sb_buf(struct xfs_mount *mp);
+extern int     xfs_sync_sb_buf(struct xfs_mount *mp, bool update_rtsb);
 extern void    xfs_sb_mount_common(struct xfs_mount *mp, struct xfs_sb *sbp);
 void           xfs_mount_sb_set_rextsize(struct xfs_mount *mp,
                        struct xfs_sb *sbp);