]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: check the realtime superblock at mount time
authorDarrick J. Wong <djwong@kernel.org>
Wed, 29 May 2024 04:11:13 +0000 (21:11 -0700)
committerChristoph Hellwig <hch@lst.de>
Tue, 6 Aug 2024 13:05:13 +0000 (06:05 -0700)
Check the realtime superblock at mount time, to ensure that the label
and uuids actually match the primary superblock on the data device.  If
the rt superblock is good, attach it to the xfs_mount so that the log
can use ordered buffers to keep this primary in sync with the primary
super on the data device.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/xfs_mount.h
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_rtalloc.h
fs/xfs/xfs_super.c

index c547d0917a86f9ca70719a224f168b21f7a507cb..2f38be9bdf86094ce3af1c60c85c1feb1a53751e 100644 (file)
@@ -85,6 +85,7 @@ typedef struct xfs_mount {
        struct super_block      *m_super;
        struct xfs_ail          *m_ail;         /* fs active log item list */
        struct xfs_buf          *m_sb_bp;       /* buffer for superblock */
+       struct xfs_buf          *m_rtsb_bp;     /* realtime superblock */
        char                    *m_rtname;      /* realtime device name */
        char                    *m_logname;     /* external log device name */
        struct xfs_da_geometry  *m_dir_geo;     /* directory block geometry */
index 8cbcac1246de722f40f3f8408719bf443d68662c..9a6244c2a65b5169057c10c721be9b9f66391049 100644 (file)
@@ -1100,6 +1100,56 @@ xfs_growfs_rt(
        return xfs_update_secondary_sbs(mp);
 }
 
+/* Read the realtime superblock and attach it to the mount. */
+int
+xfs_rtmount_readsb(
+       struct xfs_mount        *mp)
+{
+       struct xfs_buf          *bp;
+       int                     error;
+
+       if (!xfs_has_rtsb(mp))
+               return 0;
+       if (mp->m_sb.sb_rblocks == 0)
+               return 0;
+       if (mp->m_rtdev_targp == NULL) {
+               xfs_warn(mp,
+       "Filesystem has a realtime volume, use rtdev=device option");
+               return -ENODEV;
+       }
+
+       /* m_blkbb_log is not set up yet */
+       error = xfs_buf_read_uncached(mp->m_rtdev_targp, XFS_RTSB_DADDR,
+                       mp->m_sb.sb_blocksize >> BBSHIFT, XBF_NO_IOACCT, &bp,
+                       &xfs_rtsb_buf_ops);
+       if (error) {
+               xfs_warn(mp, "rt sb validate failed with error %d.", error);
+               /* bad CRC means corrupted metadata */
+               if (error == -EFSBADCRC)
+                       error = -EFSCORRUPTED;
+               return error;
+       }
+
+       mp->m_rtsb_bp = bp;
+       xfs_buf_unlock(bp);
+       return 0;
+}
+
+/* Detach the realtime superblock from the mount and free it. */
+void
+xfs_rtmount_freesb(
+       struct xfs_mount        *mp)
+{
+       struct xfs_buf          *bp = mp->m_rtsb_bp;
+
+       if (!bp)
+               return;
+
+       xfs_buf_lock(bp);
+       mp->m_rtsb_bp = NULL;
+       xfs_buf_relse(bp);
+}
+
 /*
  * Initialize realtime fields in the mount structure.
  */
index a6836da9bebef51c2df59faa05023759e3caed7c..8e2a07b8174b74737b03a42ff9e90c858ed349fb 100644 (file)
@@ -12,6 +12,10 @@ struct xfs_mount;
 struct xfs_trans;
 
 #ifdef CONFIG_XFS_RT
+/* rtgroup superblock initialization */
+int xfs_rtmount_readsb(struct xfs_mount *mp);
+void xfs_rtmount_freesb(struct xfs_mount *mp);
+
 /*
  * Initialize realtime fields in the mount structure.
  */
@@ -42,6 +46,8 @@ int xfs_rtalloc_reinit_frextents(struct xfs_mount *mp);
 #else
 # define xfs_growfs_rt(mp,in)                          (-ENOSYS)
 # define xfs_rtalloc_reinit_frextents(m)               (0)
+# define xfs_rtmount_readsb(mp)                                (0)
+# define xfs_rtmount_freesb(mp)                                ((void)0)
 static inline int              /* error */
 xfs_rtmount_init(
        xfs_mount_t     *mp)    /* file system mount structure */
index 1181628ef4bb05dc582d98aa0294cb33ff8992de..5ceff12393353620548280813ae24c58baae96e3 100644 (file)
@@ -45,6 +45,7 @@
 #include "xfs_rtbitmap.h"
 #include "xfs_exchmaps_item.h"
 #include "xfs_parent.h"
+#include "xfs_rtalloc.h"
 #include "scrub/stats.h"
 #include "scrub/rcbag_btree.h"
 
@@ -1145,6 +1146,7 @@ xfs_fs_put_super(
        xfs_filestream_unmount(mp);
        xfs_unmountfs(mp);
 
+       xfs_rtmount_freesb(mp);
        xfs_freesb(mp);
        xchk_mount_stats_free(mp);
        free_percpu(mp->m_stats.xs_stats);
@@ -1680,10 +1682,14 @@ xfs_fs_fill_super(
                goto out_free_sb;
        }
 
-       error = xfs_filestream_mount(mp);
+       error = xfs_rtmount_readsb(mp);
        if (error)
                goto out_free_sb;
 
+       error = xfs_filestream_mount(mp);
+       if (error)
+               goto out_free_rtsb;
+
        /*
         * we must configure the block size in the superblock before we run the
         * full mount process as the mount process can lookup and cache inodes.
@@ -1726,6 +1732,14 @@ xfs_fs_fill_super(
                xfs_warn(mp,
 "EXPERIMENTAL metadata directory feature in use. Use at your own risk!");
 
+       if (xfs_has_rtgroups(mp))
+               xfs_warn(mp,
+"EXPERIMENTAL realtime allocation group feature in use. Use at your own risk!");
+
+       if (xfs_has_rtsb(mp))
+               xfs_warn(mp,
+"EXPERIMENTAL realtime superblock feature in use. Use at your own risk!");
+
        if (xfs_has_reflink(mp)) {
                if (mp->m_sb.sb_rblocks) {
                        xfs_alert(mp,
@@ -1774,6 +1788,8 @@ xfs_fs_fill_super(
 
  out_filestream_unmount:
        xfs_filestream_unmount(mp);
+ out_free_rtsb:
+       xfs_rtmount_freesb(mp);
  out_free_sb:
        xfs_freesb(mp);
  out_free_scrub_stats:
@@ -1793,7 +1809,7 @@ xfs_fs_fill_super(
  out_unmount:
        xfs_filestream_unmount(mp);
        xfs_unmountfs(mp);
-       goto out_free_sb;
+       goto out_free_rtsb;
 }
 
 static int