+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,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 "libxfs.h"
+#include "libxlog.h"
#include <signal.h>
#include "command.h"
#include "init.h"
#include "malloc.h"
#include "type.h"
-static char **cmdline;
-static int ncmdline;
-char *fsdevice;
-int blkbb;
-int exitcode;
-int expert_mode;
-int force;
-xfs_mount_t xmount;
-xfs_mount_t *mp;
-libxfs_init_t x;
-xfs_agnumber_t cur_agno = NULLAGNUMBER;
+static char **cmdline;
+static int ncmdline;
+char *fsdevice;
+int blkbb;
+int exitcode;
+int expert_mode;
+static int force;
+static struct xfs_mount xmount;
+struct xfs_mount *mp;
+static struct xlog xlog;
+libxfs_init_t x;
+xfs_agnumber_t cur_agno = NULLAGNUMBER;
static void
usage(void)
exit(1);
}
-void
+static void
init(
int argc,
char **argv)
{
- xfs_sb_t *sbp;
- void *bufp = NULL;
+ struct xfs_sb *sbp;
+ struct xfs_buf *bp;
+ unsigned int agcount;
int c;
setlocale(LC_ALL, "");
else
x.dname = fsdevice;
+ x.bcache_flags = CACHE_MISCOMPARE_PURGE;
if (!libxfs_init(&x)) {
fputs(_("\nfatal error -- couldn't initialize XFS library\n"),
stderr);
exit(1);
}
- if (read_bbs(XFS_SB_DADDR, 1, &bufp, NULL)) {
+ /*
+ * Read the superblock, but don't validate it - we are a diagnostic
+ * tool and so need to be able to mount busted filesystems.
+ */
+ memset(&xmount, 0, sizeof(struct xfs_mount));
+ libxfs_buftarg_init(&xmount, x.ddev, x.logdev, x.rtdev);
+ bp = libxfs_readbuf(xmount.m_ddev_targp, XFS_SB_DADDR,
+ 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0, NULL);
+
+ if (!bp || bp->b_error) {
fprintf(stderr, _("%s: %s is invalid (cannot read first 512 "
"bytes)\n"), progname, fsdevice);
exit(1);
}
/* copy SB from buffer to in-core, converting architecture as we go */
- libxfs_sb_from_disk(&xmount.m_sb, bufp);
- xfree(bufp);
+ libxfs_sb_from_disk(&xmount.m_sb, XFS_BUF_TO_SBP(bp));
+ libxfs_putbuf(bp);
+ libxfs_purgebuf(bp);
sbp = &xmount.m_sb;
if (sbp->sb_magicnum != XFS_SB_MAGIC) {
fprintf(stderr, _("%s: %s is not a valid XFS filesystem (unexpected SB magic number 0x%08x)\n"),
progname, fsdevice, sbp->sb_magicnum);
- if (!force)
- exit(EXIT_FAILURE);
- }
-
- /*
- * Don't allow modifications to CRC enabled filesystems until we support
- * CRC recalculation in the IO path. Unless, of course, the user is in
- * the process of hitting us with a big hammer.
- */
- if (XFS_SB_VERSION_NUM(sbp) >= XFS_SB_VERSION_5 &&
- !(x.isreadonly & LIBXFS_ISREADONLY)) {
- fprintf(stderr,
- _("%s: modifications to %s are not supported in thi version.\n"
- "Use \"-r\" to run %s in read-only mode on this filesystem .\n"),
- progname, fsdevice, progname);
- if (!force)
+ if (!force) {
+ fprintf(stderr, _("Use -F to force a read attempt.\n"));
exit(EXIT_FAILURE);
+ }
}
+ agcount = sbp->sb_agcount;
mp = libxfs_mount(&xmount, sbp, x.ddev, x.logdev, x.rtdev,
LIBXFS_MOUNT_DEBUGGER);
if (!mp) {
progname, fsdevice);
exit(1);
}
+ mp->m_log = &xlog;
blkbb = 1 << mp->m_blkbb_log;
+ /* Did we limit a broken agcount in libxfs_mount? */
+ if (sbp->sb_agcount != agcount)
+ exitcode = 1;
+
/*
* xfs_check needs corrected incore superblock values
*/
if (sbp->sb_rootino != NULLFSINO &&
xfs_sb_version_haslazysbcount(&mp->m_sb)) {
- int error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
+ int error = -libxfs_initialize_perag_data(mp, sbp->sb_agcount);
if (error) {
fprintf(stderr,
_("%s: cannot init perag data (%d). Continuing anyway.\n"),
}
}
- if (xfs_sb_version_hascrc(&mp->m_sb))
+ if (xfs_sb_version_hassparseinodes(&mp->m_sb))
+ type_set_tab_spcrc();
+ else if (xfs_sb_version_hascrc(&mp->m_sb))
type_set_tab_crc();
push_cur();
int c, i, done = 0;
char *input;
char **v;
+ int start_iocur_sp;
- pushfile(stdin);
init(argc, argv);
+ start_iocur_sp = iocur_sp;
for (i = 0; !done && i < ncmdline; i++) {
v = breakline(cmdline[i], &c);
goto close_devices;
}
+ pushfile(stdin);
while (!done) {
if ((input = fetchline()) == NULL)
break;
}
close_devices:
+ /*
+ * Make sure that we pop the all the buffer contexts we hold so that
+ * they are released before we purge the caches during unmount.
+ */
+ while (iocur_sp > start_iocur_sp)
+ pop_cur();
+ libxfs_umount(mp);
if (x.ddev)
libxfs_device_close(x.ddev);
if (x.logdev && x.logdev != x.ddev)
libxfs_device_close(x.logdev);
if (x.rtdev)
libxfs_device_close(x.rtdev);
+ libxfs_destroy();
+
return exitcode;
}