| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| */ |
| |
| #include "libxfs.h" |
| #include "globals.h" |
| #include "agheader.h" |
| #include "protos.h" |
| #include "err_protos.h" |
| |
| static void |
| no_sb(void) |
| { |
| do_warn(_("Sorry, could not find valid secondary superblock\n")); |
| do_warn(_("Exiting now.\n")); |
| exit(1); |
| } |
| |
| char * |
| alloc_ag_buf(int size) |
| { |
| char *bp; |
| |
| bp = (char *)memalign(libxfs_device_alignment(), size); |
| if (!bp) |
| do_error(_("could not allocate ag header buffer (%d bytes)\n"), |
| size); |
| return(bp); |
| } |
| |
| /* |
| * this has got to be big enough to hold 4 sectors |
| */ |
| #define MAX_SECTSIZE (512 * 1024) |
| |
| /* ARGSUSED */ |
| void |
| phase1(xfs_mount_t *mp) |
| { |
| xfs_sb_t *sb; |
| char *ag_bp; |
| int rval; |
| |
| do_log(_("Phase 1 - find and verify superblock...\n")); |
| |
| primary_sb_modified = 0; |
| need_root_inode = 0; |
| need_root_dotdot = 0; |
| need_rbmino = 0; |
| need_rsumino = 0; |
| lost_quotas = 0; |
| |
| /* |
| * get AG 0 into ag header buf |
| */ |
| ag_bp = alloc_ag_buf(MAX_SECTSIZE); |
| sb = (xfs_sb_t *) ag_bp; |
| |
| rval = get_sb(sb, 0LL, MAX_SECTSIZE, 0); |
| if (rval == XR_EOF) |
| do_error(_("error reading primary superblock\n")); |
| |
| /* |
| * is this really an sb, verify internal consistency |
| */ |
| if (rval != XR_OK) { |
| do_warn(_("bad primary superblock - %s !!!\n"), |
| err_string(rval)); |
| if (!find_secondary_sb(sb)) |
| no_sb(); |
| primary_sb_modified = 1; |
| } else if ((rval = verify_set_primary_sb(sb, 0, |
| &primary_sb_modified)) != XR_OK) { |
| do_warn(_("couldn't verify primary superblock - %s !!!\n"), |
| err_string(rval)); |
| if (!find_secondary_sb(sb)) |
| no_sb(); |
| primary_sb_modified = 1; |
| } |
| |
| /* |
| * Check bad_features2 and make sure features2 the same as |
| * bad_features (ORing the two together). Leave bad_features2 |
| * set so older kernels can still use it and not mount unsupported |
| * filesystems when it reads bad_features2. |
| */ |
| if (sb->sb_bad_features2 != 0 && |
| sb->sb_bad_features2 != sb->sb_features2) { |
| sb->sb_features2 |= sb->sb_bad_features2; |
| sb->sb_bad_features2 = sb->sb_features2; |
| primary_sb_modified = 1; |
| do_warn(_("superblock has a features2 mismatch, correcting\n")); |
| } |
| |
| /* |
| * apply any version changes or conversions after the primary |
| * superblock has been verified or repaired |
| * |
| * Send output to stdout as do_log and everything else in repair |
| * is sent to stderr and there is no "quiet" option. xfs_admin |
| * will filter stderr but not stdout. This situation must be improved. |
| */ |
| if (convert_lazy_count) { |
| if (lazy_count && !xfs_sb_version_haslazysbcount(sb)) { |
| sb->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; |
| sb->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT; |
| sb->sb_bad_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT; |
| primary_sb_modified = 1; |
| printf(_("Enabling lazy-counters\n")); |
| } else if (!lazy_count && xfs_sb_version_haslazysbcount(sb)) { |
| if (XFS_SB_VERSION_NUM(sb) == XFS_SB_VERSION_5) { |
| printf( |
| _("Cannot disable lazy-counters on V5 fs\n")); |
| exit(1); |
| } |
| sb->sb_features2 &= ~XFS_SB_VERSION2_LAZYSBCOUNTBIT; |
| sb->sb_bad_features2 &= ~XFS_SB_VERSION2_LAZYSBCOUNTBIT; |
| printf(_("Disabling lazy-counters\n")); |
| primary_sb_modified = 1; |
| } else { |
| printf(_("Lazy-counters are already %s\n"), |
| lazy_count ? _("enabled") : _("disabled")); |
| exit(0); /* no conversion required, exit */ |
| } |
| } |
| |
| /* shared_vn should be zero */ |
| if (sb->sb_shared_vn) { |
| do_warn(_("resetting shared_vn to zero\n")); |
| sb->sb_shared_vn = 0; |
| primary_sb_modified = 1; |
| } |
| |
| if (primary_sb_modified) { |
| if (!no_modify) { |
| do_warn(_("writing modified primary superblock\n")); |
| write_primary_sb(sb, sb->sb_sectsize); |
| } else { |
| do_warn(_("would write modified primary superblock\n")); |
| } |
| } |
| |
| /* |
| * misc. global var initialization |
| */ |
| sb_ifree = sb_icount = sb_fdblocks = sb_frextents = 0; |
| |
| free(sb); |
| } |