+// 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"
#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);
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 }
};
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) {
}
}
- 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"
"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;
}
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;
}
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"));
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];
}
}
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;
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;
}
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");
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;
}
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 */
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