]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: refactor superblock verifiers
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 5 Oct 2018 02:36:11 +0000 (21:36 -0500)
committerEric Sandeen <sandeen@redhat.com>
Fri, 5 Oct 2018 02:36:11 +0000 (21:36 -0500)
Source kernel commit: eca383fcd63b452cf533505154135da2a1f70227

Split the superblock verifier into the common checks, the read-time
checks, and the write-time check functions.  No functional changes, but
we're setting up to add more write-only checks.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/xfs_sb.c

index 9a48d9301355172ea0226c813b677032bed493ca..c9ad7e3646af8cfef034e2c823c85a66ff63c000 100644 (file)
@@ -93,80 +93,94 @@ xfs_perag_put(
        trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_);
 }
 
-/*
- * Check the validity of the SB found.
- */
+/* Check all the superblock fields we care about when reading one in. */
 STATIC int
-xfs_mount_validate_sb(
-       xfs_mount_t     *mp,
-       xfs_sb_t        *sbp,
-       bool            check_inprogress,
-       bool            check_version)
+xfs_validate_sb_read(
+       struct xfs_mount        *mp,
+       struct xfs_sb           *sbp)
 {
-       uint32_t        agcount = 0;
-       uint32_t        rem;
-
-       if (sbp->sb_magicnum != XFS_SB_MAGIC) {
-               xfs_warn(mp, "bad magic number");
-               return -EWRONGFS;
-       }
-
-
-       if (!xfs_sb_good_version(sbp)) {
-               xfs_warn(mp, "bad version");
-               return -EWRONGFS;
-       }
+       if (XFS_SB_VERSION_NUM(sbp) != XFS_SB_VERSION_5)
+               return 0;
 
        /*
-        * Version 5 superblock feature mask validation. Reject combinations the
-        * kernel cannot support up front before checking anything else. For
-        * write validation, we don't need to check feature masks.
+        * Version 5 superblock feature mask validation. Reject combinations
+        * the kernel cannot support up front before checking anything else.
         */
-       if (check_version && XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) {
-               if (xfs_sb_has_compat_feature(sbp,
-                                       XFS_SB_FEAT_COMPAT_UNKNOWN)) {
-                       xfs_warn(mp,
+       if (xfs_sb_has_compat_feature(sbp, XFS_SB_FEAT_COMPAT_UNKNOWN)) {
+               xfs_warn(mp,
 "Superblock has unknown compatible features (0x%x) enabled.",
-                               (sbp->sb_features_compat &
-                                               XFS_SB_FEAT_COMPAT_UNKNOWN));
-                       xfs_warn(mp,
+                       (sbp->sb_features_compat & XFS_SB_FEAT_COMPAT_UNKNOWN));
+               xfs_warn(mp,
 "Using a more recent kernel is recommended.");
-               }
+       }
 
-               if (xfs_sb_has_ro_compat_feature(sbp,
-                                       XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
-                       xfs_alert(mp,
+       if (xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
+               xfs_alert(mp,
 "Superblock has unknown read-only compatible features (0x%x) enabled.",
-                               (sbp->sb_features_ro_compat &
-                                               XFS_SB_FEAT_RO_COMPAT_UNKNOWN));
-                       if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
-                               xfs_warn(mp,
+                       (sbp->sb_features_ro_compat &
+                                       XFS_SB_FEAT_RO_COMPAT_UNKNOWN));
+               if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
+                       xfs_warn(mp,
 "Attempted to mount read-only compatible filesystem read-write.");
-                               xfs_warn(mp,
+                       xfs_warn(mp,
 "Filesystem can only be safely mounted read only.");
 
-                               return -EINVAL;
-                       }
-               }
-               if (xfs_sb_has_incompat_feature(sbp,
-                                       XFS_SB_FEAT_INCOMPAT_UNKNOWN)) {
-                       xfs_warn(mp,
-"Superblock has unknown incompatible features (0x%x) enabled.",
-                               (sbp->sb_features_incompat &
-                                               XFS_SB_FEAT_INCOMPAT_UNKNOWN));
-                       xfs_warn(mp,
-"Filesystem can not be safely mounted by this kernel.");
                        return -EINVAL;
                }
-       } else if (xfs_sb_version_hascrc(sbp)) {
-               /*
-                * We can't read verify the sb LSN because the read verifier is
-                * called before the log is allocated and processed. We know the
-                * log is set up before write verifier (!check_version) calls,
-                * so just check it here.
-                */
-               if (!xfs_log_check_lsn(mp, sbp->sb_lsn))
-                       return -EFSCORRUPTED;
+       }
+       if (xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_UNKNOWN)) {
+               xfs_warn(mp,
+"Superblock has unknown incompatible features (0x%x) enabled.",
+                       (sbp->sb_features_incompat &
+                                       XFS_SB_FEAT_INCOMPAT_UNKNOWN));
+               xfs_warn(mp,
+"Filesystem cannot be safely mounted by this kernel.");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* Check all the superblock fields we care about when writing one out. */
+STATIC int
+xfs_validate_sb_write(
+       struct xfs_mount        *mp,
+       struct xfs_sb           *sbp)
+{
+       if (XFS_SB_VERSION_NUM(sbp) != XFS_SB_VERSION_5)
+               return 0;
+
+       /* XXX: For write validation, we don't need to check feature masks?? */
+
+       /*
+        * We can't read verify the sb LSN because the read verifier is called
+        * before the log is allocated and processed. We know the log is set up
+        * before write verifier calls, so check it here.
+        */
+       if (!xfs_log_check_lsn(mp, sbp->sb_lsn))
+               return -EFSCORRUPTED;
+
+       return 0;
+}
+
+/* Check the validity of the SB. */
+STATIC int
+xfs_validate_sb_common(
+       struct xfs_mount        *mp,
+       struct xfs_buf          *bp,
+       struct xfs_sb           *sbp)
+{
+       uint32_t                agcount = 0;
+       uint32_t                rem;
+
+       if (sbp->sb_magicnum != XFS_SB_MAGIC) {
+               xfs_warn(mp, "bad magic number");
+               return -EWRONGFS;
+       }
+
+       if (!xfs_sb_good_version(sbp)) {
+               xfs_warn(mp, "bad version");
+               return -EWRONGFS;
        }
 
        if (xfs_sb_version_has_pquotino(sbp)) {
@@ -578,29 +592,6 @@ xfs_sb_to_disk(
        }
 }
 
-static int
-xfs_sb_verify(
-       struct xfs_buf  *bp,
-       bool            check_version)
-{
-       struct xfs_mount *mp = bp->b_target->bt_mount;
-       struct xfs_sb   sb;
-
-       /*
-        * Use call variant which doesn't convert quota flags from disk
-        * format, because xfs_mount_validate_sb checks the on-disk flags.
-        */
-       __xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp), false);
-
-       /*
-        * Only check the in progress field for the primary superblock as
-        * mkfs.xfs doesn't clear it from secondary superblocks.
-        */
-       return xfs_mount_validate_sb(mp, &sb,
-                                    bp->b_maps[0].bm_bn == XFS_SB_DADDR,
-                                    check_version);
-}
-
 /*
  * If the superblock has the CRC feature bit set or the CRC field is non-null,
  * check that the CRC is valid.  We check the CRC field is non-null because a
@@ -615,11 +606,12 @@ xfs_sb_verify(
  */
 static void
 xfs_sb_read_verify(
-       struct xfs_buf  *bp)
+       struct xfs_buf          *bp)
 {
-       struct xfs_mount *mp = bp->b_target->bt_mount;
-       struct xfs_dsb  *dsb = XFS_BUF_TO_SBP(bp);
-       int             error;
+       struct xfs_sb           sb;
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
+       struct xfs_dsb          *dsb = XFS_BUF_TO_SBP(bp);
+       int                     error;
 
        /*
         * open code the version check to avoid needing to convert the entire
@@ -639,7 +631,16 @@ xfs_sb_read_verify(
                        }
                }
        }
-       error = xfs_sb_verify(bp, true);
+
+       /*
+        * Check all the superblock fields.  Don't byteswap the xquota flags
+        * because _verify_common checks the on-disk values.
+        */
+       __xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp), false);
+       error = xfs_validate_sb_common(mp, bp, &sb);
+       if (error)
+               goto out_error;
+       error = xfs_validate_sb_read(mp, &sb);
 
 out_error:
        if (error == -EFSCORRUPTED || error == -EFSBADCRC)
@@ -673,15 +674,22 @@ static void
 xfs_sb_write_verify(
        struct xfs_buf          *bp)
 {
+       struct xfs_sb           sb;
        struct xfs_mount        *mp = bp->b_target->bt_mount;
        struct xfs_buf_log_item *bip = bp->b_log_item;
        int                     error;
 
-       error = xfs_sb_verify(bp, false);
-       if (error) {
-               xfs_verifier_error(bp, error, __this_address);
-               return;
-       }
+       /*
+        * Check all the superblock fields.  Don't byteswap the xquota flags
+        * because _verify_common checks the on-disk values.
+        */
+       __xfs_sb_from_disk(&sb, XFS_BUF_TO_SBP(bp), false);
+       error = xfs_validate_sb_common(mp, bp, &sb);
+       if (error)
+               goto out_error;
+       error = xfs_validate_sb_write(mp, &sb);
+       if (error)
+               goto out_error;
 
        if (!xfs_sb_version_hascrc(&mp->m_sb))
                return;
@@ -690,6 +698,10 @@ xfs_sb_write_verify(
                XFS_BUF_TO_SBP(bp)->sb_lsn = cpu_to_be64(bip->bli_item.li_lsn);
 
        xfs_buf_update_cksum(bp, XFS_SB_CRC_OFF);
+       return;
+
+out_error:
+       xfs_verifier_error(bp, error, __this_address);
 }
 
 const struct xfs_buf_ops xfs_sb_buf_ops = {