]> www.infradead.org Git - users/hch/misc.git/commitdiff
xfs: update realtime super every time we update the primary fs super
authorDarrick J. Wong <djwong@kernel.org>
Wed, 29 May 2024 04:11:13 +0000 (21:11 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 24 Jul 2024 05:33:35 +0000 (22:33 -0700)
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>
fs/xfs/libxfs/xfs_rtgroup.c
fs/xfs/libxfs/xfs_rtgroup.h
fs/xfs/libxfs/xfs_sb.c
fs/xfs/libxfs/xfs_sb.h
fs/xfs/xfs_buf_item_recover.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_trans.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_trans_buf.c

index 519d2829d86b775b2b8dbddbd0bb49722a6a8935..975fcdfb29a4630c8726990cf683f72e284b4f24 100644 (file)
@@ -350,3 +350,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_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_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_rtgroup_log_super(
+       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_rtgroup_update_super(rtsb_bp, sb_bp);
+       xfs_trans_ordered_buf(tp, rtsb_bp);
+       return rtsb_bp;
+}
index 8443fd154796823288686fab5214012233da12e5..4cbdb6e2bb1b450bf89ce098f542656caa620ecd 100644 (file)
@@ -213,8 +213,15 @@ 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);
+struct xfs_buf *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)      (NULL)
 #endif /* CONFIG_XFS_RT */
 
 #endif /* __LIBXFS_RTGROUP_H */
index 93e56e934da737d49937a678d0d3b078c6226412..69f518d83de04f2217f4da16482fc97421a7618b 100644 (file)
@@ -27,6 +27,7 @@
 #include "xfs_ag.h"
 #include "xfs_rtbitmap.h"
 #include "xfs_exchrange.h"
+#include "xfs_rtgroup.h"
 
 /*
  * Physical superblock buffer manipulations. Shared with libxfs in userspace.
@@ -1267,10 +1268,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);
@@ -1280,6 +1283,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_rtgroup_log_super(tp, bp);
+               if (rtsb_bp)
+                       xfs_trans_bhold(tp, rtsb_bp);
+       }
        xfs_trans_set_sync(tp);
        error = xfs_trans_commit(tp);
        if (error)
@@ -1288,7 +1296,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 37b1ed1bc2095e42561764196a932cb11fb4d7f7..977aa579eaec6c7b9f8efa4e4c6f7002a7c8772a 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);
 extern void    xfs_sb_from_disk(struct xfs_sb *to, struct xfs_dsb *from);
 extern void    xfs_sb_to_disk(struct xfs_dsb *to, struct xfs_sb *from);
index 09e893cf563cb98e740609743db74523148ee2c5..8afae95d1687ddf90402eb8cc891a827c32a57eb 100644 (file)
@@ -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
@@ -995,6 +996,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 rt super if we just recovered the primary fs
+                * super.
+                */
+               if (xfs_has_rtsb(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:
index 792b6e35ba719e5f53e0b063e8f9f5eae57cd7e7..e281754973df2e4a35c236fcfee39e2e5d3c4295 100644 (file)
@@ -1147,7 +1147,7 @@ xfs_ioc_setlabel(
         * buffered reads from userspace (i.e. from blkid) are invalidated,
         * and userspace will see the newly-written label.
         */
-       error = xfs_sync_sb_buf(mp);
+       error = xfs_sync_sb_buf(mp, true);
        if (error)
                goto out;
        /*
@@ -1158,6 +1158,8 @@ xfs_ioc_setlabel(
        mutex_unlock(&mp->m_growlock);
 
        invalidate_bdev(mp->m_ddev_targp->bt_bdev);
+       if (xfs_has_rtsb(mp) && mp->m_rtdev_targp)
+               invalidate_bdev(mp->m_rtdev_targp->bt_bdev);
 
 out:
        mnt_drop_write_file(filp);
index bdf3704dc301185ae8a855d67bf5c70b2f4b9ca0..5fd1765b3dcd8726856a288af1b2125aa4191ec0 100644 (file)
@@ -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;
 
index f06cc0f41665ad5f63b69126fdd2d035e4b6dde9..f97e5c416efad126dd2f5056384d564f2f284b4d 100644 (file)
@@ -214,6 +214,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 *);
index e28ab74af4f0e1c2514656c41591e924c3ea53b0..8e886ecfd69a3b6cf4e4566a846da9024472d7d3 100644 (file)
@@ -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