]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - db/sb.c
xfs: remove suport for filesystems without unwritten extent flag
[thirdparty/xfsprogs-dev.git] / db / sb.c
diff --git a/db/sb.c b/db/sb.c
index d178f58ff33ff24395eb5351e7b9b1eb45464d5e..5059b261ceff7fd5297bbf3abae5fc029fed35f9 100644 (file)
--- a/db/sb.c
+++ b/db/sb.c
@@ -1,23 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <xfs/libxfs.h>
-#include <xfs/libxlog.h>
+#include "libxfs.h"
+#include "libxlog.h"
 #include "command.h"
 #include "type.h"
 #include "faddr.h"
@@ -29,6 +17,8 @@
 #include "output.h"
 #include "init.h"
 
+#define uuid_equal(s,d)                (platform_uuid_compare((s),(d)) == 0)
+
 static int     sb_f(int argc, char **argv);
 static void     sb_help(void);
 static int     uuid_f(int argc, char **argv);
@@ -118,9 +108,11 @@ const field_t      sb_flds[] = {
                C1, 0, TYP_NONE },
        { "features_log_incompat", FLDT_UINT32X, OI(OFF(features_log_incompat)),
                C1, 0, TYP_NONE },
-       { "crc", FLDT_UINT32X, OI(OFF(crc)), C1, 0, TYP_NONE },
+       { "crc", FLDT_CRC, OI(OFF(crc)), C1, 0, TYP_NONE },
+       { "spino_align", FLDT_EXTLEN, OI(OFF(spino_align)), C1, 0, TYP_NONE },
        { "pquotino", FLDT_INO, OI(OFF(pquotino)), C1, 0, TYP_INODE },
        { "lsn", FLDT_UINT64X, OI(OFF(lsn)), C1, 0, TYP_NONE },
+       { "meta_uuid", FLDT_UUID, OI(OFF(meta_uuid)), C1, 0, TYP_NONE },
        { NULL }
 };
 
@@ -225,8 +217,7 @@ int xlog_recover_do_trans(struct xlog *log, xlog_recover_t *t, int p)
 int
 sb_logcheck(void)
 {
-       struct xlog     log;
-       xfs_daddr_t     head_blk, tail_blk;
+       int             dirty;
 
        if (mp->m_sb.sb_logstart) {
                if (x.logdev && x.logdev != x.ddev) {
@@ -242,26 +233,13 @@ sb_logcheck(void)
                }
        }
 
-       memset(&log, 0, sizeof(log));
        libxfs_buftarg_init(mp, x.ddev, x.logdev, x.rtdev);
-       x.logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
-       x.logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart);
-       x.lbsize = BBSIZE;
-       if (xfs_sb_version_hassector(&mp->m_sb))
-               x.lbsize <<= (mp->m_sb.sb_logsectlog - BBSHIFT);
-
-       log.l_dev = mp->m_logdev_targp;
-       log.l_logsize = BBTOB(log.l_logBBsize);
-       log.l_logBBsize = x.logBBsize;
-       log.l_logBBstart = x.logBBstart;
-       log.l_sectBBsize  = BTOBB(x.lbsize);
-       log.l_mp = mp;
-
-       if (xlog_find_tail(&log, &head_blk, &tail_blk)) {
+
+       dirty = xlog_is_dirty(mp, mp->m_log, &x, 0);
+       if (dirty == -1) {
                dbprintf(_("ERROR: cannot find log head/tail, run xfs_repair\n"));
                return 0;
-       }
-       if (head_blk != tail_blk) {
+       } else if (dirty == 1) {
                dbprintf(_(
 "ERROR: The filesystem has valuable metadata changes in a log which needs to\n"
 "be replayed.  Mount the filesystem to replay the log, and unmount it before\n"
@@ -271,26 +249,39 @@ sb_logcheck(void)
 "of the filesystem before doing this.\n"), progname);
                return 0;
        }
+       /* Log is clean */
        return 1;
 }
 
 static int
 sb_logzero(uuid_t *uuidp)
 {
+       int     cycle = XLOG_INIT_CYCLE;
+       int     error;
+
        if (!sb_logcheck())
                return 0;
 
+       /*
+        * The log must always move forward on v5 superblocks. Bump it to the
+        * next cycle.
+        */
+       if (xfs_sb_version_hascrc(&mp->m_sb))
+               cycle = mp->m_log->l_curr_cycle + 1;
+
        dbprintf(_("Clearing log and setting UUID\n"));
 
-       if (libxfs_log_clear(mp->m_logdev_targp,
+       error =  libxfs_log_clear(mp->m_logdev_targp, NULL,
                        XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
                        (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
                        uuidp,
                        xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1,
-                       mp->m_sb.sb_logsunit, XLOG_FMT)) {
+                       mp->m_sb.sb_logsunit, XLOG_FMT, cycle, true);
+       if (error) {
                dbprintf(_("ERROR: cannot clear the log\n"));
                return 0;
        }
+
        return 1;
 }
 
@@ -334,8 +325,34 @@ do_uuid(xfs_agnumber_t agno, uuid_t *uuid)
                return &uu;
        }
        /* set uuid */
+       if (!xfs_sb_version_hascrc(&tsb))
+               goto write;
+       /*
+        * If we have CRCs, and this UUID differs from that stamped in the
+        * metadata, set the incompat flag and copy the old one to the
+        * metadata-specific location.
+        *
+        * If we are setting the user-visible UUID back to match the metadata
+        * UUID, clear the metadata-specific location and the incompat flag.
+        */
+       if (!xfs_sb_version_hasmetauuid(&tsb) &&
+           !uuid_equal(uuid, &mp->m_sb.sb_meta_uuid)) {
+               mp->m_sb.sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_META_UUID;
+               tsb.sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_META_UUID;
+               memcpy(&tsb.sb_meta_uuid, &tsb.sb_uuid, sizeof(uuid_t));
+       } else if (xfs_sb_version_hasmetauuid(&tsb) &&
+                  uuid_equal(uuid, &mp->m_sb.sb_meta_uuid)) {
+               memset(&tsb.sb_meta_uuid, 0, sizeof(uuid_t));
+               /* Write those zeros now; it's ignored once we clear the flag */
+               libxfs_sb_to_disk(iocur_top->data, &tsb);
+               mp->m_sb.sb_features_incompat &=
+                                               ~XFS_SB_FEAT_INCOMPAT_META_UUID;
+               tsb.sb_features_incompat &= ~XFS_SB_FEAT_INCOMPAT_META_UUID;
+       }
+
+write:
        memcpy(&tsb.sb_uuid, uuid, sizeof(uuid_t));
-       libxfs_sb_to_disk(iocur_top->data, &tsb, XFS_SB_UUID);
+       libxfs_sb_to_disk(iocur_top->data, &tsb);
        write_cur();
        return uuid;
 }
@@ -376,6 +393,17 @@ uuid_f(
                        memcpy(&uu, uup, sizeof(uuid_t));
                        platform_uuid_unparse(&uu, bp);
                        dbprintf(_("old UUID = %s\n"), bp);
+               } else if (!strcasecmp(argv[1], "restore")) {
+                       xfs_sb_t        tsb;
+
+                       if (!get_sb(0, &tsb))
+                               return 0;
+
+                       /* Not set; nothing to do.  Success! */
+                       if (!xfs_sb_version_hasmetauuid(&tsb))
+                               return 0;
+
+                       memcpy(&uu, mp->m_sb.sb_meta_uuid, sizeof(uuid_t));
                } else {
                        if (platform_uuid_parse(argv[1], &uu)) {
                                dbprintf(_("invalid UUID\n"));
@@ -488,7 +516,7 @@ do_label(xfs_agnumber_t agno, char *label)
        memset(&tsb.sb_fname, 0, sizeof(tsb.sb_fname));
        memcpy(&tsb.sb_fname, label, len);
        memcpy(&lbl[0], &tsb.sb_fname, sizeof(tsb.sb_fname));
-       libxfs_sb_to_disk(iocur_top->data, &tsb, XFS_SB_FNAME);
+       libxfs_sb_to_disk(iocur_top->data, &tsb);
        write_cur();
        return &lbl[0];
 }
@@ -566,10 +594,9 @@ version_help(void)
 }
 
 static int
-do_version(xfs_agnumber_t agno, __uint16_t version, __uint32_t features)
+do_version(xfs_agnumber_t agno, uint16_t version, uint32_t features)
 {
        xfs_sb_t        tsb;
-       __int64_t       fields = 0;
 
        if (!get_sb(agno, &tsb))
                return 0;
@@ -583,14 +610,12 @@ do_version(xfs_agnumber_t agno, __uint16_t version, __uint32_t features)
        if ((version & XFS_SB_VERSION_LOGV2BIT) &&
                                        !xfs_sb_version_haslogv2(&tsb)) {
                tsb.sb_logsunit = 1;
-               fields |= (1LL << XFS_SBS_LOGSUNIT);
        }
 
        tsb.sb_versionnum = version;
        tsb.sb_features2 = features;
        tsb.sb_bad_features2 = features;
-       fields |= XFS_SB_VERSIONNUM | XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;
-       libxfs_sb_to_disk(iocur_top->data, &tsb, fields);
+       libxfs_sb_to_disk(iocur_top->data, &tsb);
        write_cur();
        return 1;
 }
@@ -612,23 +637,29 @@ version_string(
        else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5)
                strcpy(s, "V5");
 
+       /*
+        * We assume the state of these features now, so macros don't exist for
+        * them any more.
+        */
+       if (sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT)
+               strcat(s, ",NLINK");
+       if (sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT)
+               strcat(s, ",SHARED");
+       if (sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)
+               strcat(s, ",DIRV2");
+
        if (xfs_sb_version_hasattr(sbp))
                strcat(s, ",ATTR");
-       if (xfs_sb_version_hasnlink(sbp))
-               strcat(s, ",NLINK");
        if (xfs_sb_version_hasquota(sbp))
                strcat(s, ",QUOTA");
        if (xfs_sb_version_hasalign(sbp))
                strcat(s, ",ALIGN");
        if (xfs_sb_version_hasdalign(sbp))
                strcat(s, ",DALIGN");
-       if (xfs_sb_version_hasshared(sbp))
-               strcat(s, ",SHARED");
-       if (xfs_sb_version_hasdirv2(sbp))
-               strcat(s, ",DIRV2");
        if (xfs_sb_version_haslogv2(sbp))
                strcat(s, ",LOGV2");
-       if (xfs_sb_version_hasextflgbit(sbp))
+       /* This feature is required now as well */
+       if (sbp->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT)
                strcat(s, ",EXTFLG");
        if (xfs_sb_version_hassector(sbp))
                strcat(s, ",SECTOR");
@@ -644,6 +675,18 @@ version_string(
                strcat(s, ",PROJID32BIT");
        if (xfs_sb_version_hascrc(sbp))
                strcat(s, ",CRC");
+       if (xfs_sb_version_hasftype(sbp))
+               strcat(s, ",FTYPE");
+       if (xfs_sb_version_hasfinobt(sbp))
+               strcat(s, ",FINOBT");
+       if (xfs_sb_version_hassparseinodes(sbp))
+               strcat(s, ",SPARSE_INODES");
+       if (xfs_sb_version_hasmetauuid(sbp))
+               strcat(s, ",META_UUID");
+       if (xfs_sb_version_hasrmapbt(sbp))
+               strcat(s, ",RMAPBT");
+       if (xfs_sb_version_hasreflink(sbp))
+               strcat(s, ",REFLINK");
        return s;
 }
 
@@ -658,8 +701,8 @@ version_f(
        int             argc,
        char            **argv)
 {
-       __uint16_t      version = 0;
-       __uint32_t      features = 0;
+       uint16_t        version = 0;
+       uint32_t        features = 0;
        xfs_agnumber_t  ag;
 
        if (argc == 2) {        /* WRITE VERSION */
@@ -683,7 +726,8 @@ version_f(
                                version = 0x0034 | XFS_SB_VERSION_EXTFLGBIT;
                                break;
                        case XFS_SB_VERSION_4:
-                               if (xfs_sb_version_hasextflgbit(&mp->m_sb))
+                               if (mp->m_sb.sb_versionnum &
+                                               XFS_SB_VERSION_EXTFLGBIT)
                                        dbprintf(
                _("unwritten extents flag is already enabled\n"));
                                else