blob: b24965b263a1836d645b54e2ff69bafc92a477ae [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* All Rights Reserved.
*/
#include "libxfs.h"
#include "err_protos.h"
#include "globals.h"
#include "versions.h"
/*
* filesystem feature global vars, set to 1 if the feature
* is on, 0 otherwise
*/
int fs_attributes;
int fs_attributes2;
int fs_inode_nlink;
int fs_quotas;
int fs_aligned_inodes;
int fs_sb_feature_bits;
int fs_has_extflgbit;
/*
* inode chunk alignment, fsblocks
*/
xfs_extlen_t fs_ino_alignment;
void
update_sb_version(
struct xfs_mount *mp)
{
if (fs_attributes && !xfs_has_attr(mp))
xfs_sb_version_addattr(&mp->m_sb);
if (fs_attributes2 && !xfs_has_attr2(mp))
xfs_sb_version_addattr2(&mp->m_sb);
/* V2 inode conversion is now always going to happen */
if (!(mp->m_sb.sb_versionnum & XFS_SB_VERSION_NLINKBIT))
mp->m_sb.sb_versionnum |= XFS_SB_VERSION_NLINKBIT;
/*
* fix up the superblock version number and feature bits,
* turn off quota bits and flags if the filesystem doesn't
* have quotas.
*/
if (fs_quotas) {
if (!xfs_has_quota(mp))
xfs_sb_version_addquota(&mp->m_sb);
/*
* protect against stray bits in the quota flag field
*/
if (mp->m_sb.sb_qflags & ~XFS_MOUNT_QUOTA_ALL) {
/*
* update the incore superblock, if we're in
* no_modify mode, it'll never get flushed out
* so this is ok.
*/
do_warn(_("bogus quota flags 0x%x set in superblock"),
mp->m_sb.sb_qflags & ~XFS_MOUNT_QUOTA_ALL);
mp->m_sb.sb_qflags &= XFS_MOUNT_QUOTA_ALL;
if (!no_modify)
do_warn(_(", bogus flags will be cleared\n"));
else
do_warn(_(", bogus flags would be cleared\n"));
}
} else {
mp->m_sb.sb_qflags = 0;
if (xfs_has_quota(mp)) {
lost_quotas = 1;
mp->m_sb.sb_versionnum &= ~XFS_SB_VERSION_QUOTABIT;
}
}
if (!fs_aligned_inodes && xfs_has_align(mp))
mp->m_sb.sb_versionnum &= ~XFS_SB_VERSION_ALIGNBIT;
mp->m_features &= ~(XFS_FEAT_QUOTA | XFS_FEAT_ALIGN);
mp->m_features |= libxfs_sb_version_to_features(&mp->m_sb);
}
/*
* returns 0 if things are fine, 1 if we don't understand
* this superblock version. Sets superblock geometry-dependent
* global variables.
*/
int
parse_sb_version(
struct xfs_mount *mp)
{
fs_attributes = 0;
fs_attributes2 = 0;
fs_inode_nlink = 1;
fs_quotas = 0;
fs_aligned_inodes = 0;
fs_sb_feature_bits = 0;
fs_ino_alignment = 0;
fs_has_extflgbit = 1;
have_uquotino = 0;
have_gquotino = 0;
have_pquotino = 0;
if (mp->m_sb.sb_versionnum & XFS_SB_VERSION_SHAREDBIT) {
do_warn(_("Shared Version bit set. Not supported. Ever.\n"));
return 1;
}
/*
* ok, check to make sure that the sb isn't newer
* than we are
*/
if (!xfs_sb_good_version(&mp->m_sb)) {
do_warn(_("WARNING: unknown superblock version %d\n"),
XFS_SB_VERSION_NUM(&mp->m_sb));
do_warn(
_("This filesystem contains features not understood by this program.\n"));
return(1);
}
if (XFS_SB_VERSION_NUM(&mp->m_sb) >= XFS_SB_VERSION_4)
fs_sb_feature_bits = 1;
/* Look for V5 feature flags we don't know about */
if (XFS_SB_VERSION_NUM(&mp->m_sb) >= XFS_SB_VERSION_5 &&
(xfs_sb_has_compat_feature(&mp->m_sb, XFS_SB_FEAT_COMPAT_UNKNOWN) ||
xfs_sb_has_ro_compat_feature(&mp->m_sb, XFS_SB_FEAT_RO_COMPAT_UNKNOWN) ||
xfs_sb_has_incompat_feature(&mp->m_sb, XFS_SB_FEAT_INCOMPAT_UNKNOWN))) {
do_warn(
_("Superblock has unknown compat/rocompat/incompat features (0x%x/0x%x/0x%x).\n"
"Using a more recent xfs_repair is recommended.\n"),
mp->m_sb.sb_features_compat & XFS_SB_FEAT_COMPAT_UNKNOWN,
mp->m_sb.sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_UNKNOWN,
mp->m_sb.sb_features_incompat & XFS_SB_FEAT_INCOMPAT_UNKNOWN);
return 1;
}
if (xfs_has_attr(mp))
fs_attributes = 1;
if (xfs_has_attr2(mp))
fs_attributes2 = 1;
if (!(mp->m_sb.sb_versionnum & XFS_SB_VERSION_NLINKBIT)) {
if (!no_modify) {
do_warn(
_("WARNING: you have a V1 inode filesystem. It will be converted to a\n"
"\tversion 2 inode filesystem. If you do not want this, run an older\n"
"\tversion of xfs_repair.\n"));
} else {
do_warn(
_("WARNING: you have a V1 inode filesystem. It would be converted to a\n"
"\tversion 2 inode filesystem. If you do not want this, run an older\n"
"\tversion of xfs_repair.\n"));
}
}
if (xfs_has_quota(mp)) {
fs_quotas = 1;
if (mp->m_sb.sb_uquotino != 0 && mp->m_sb.sb_uquotino != NULLFSINO)
have_uquotino = 1;
if (mp->m_sb.sb_gquotino != 0 && mp->m_sb.sb_gquotino != NULLFSINO)
have_gquotino = 1;
if (mp->m_sb.sb_pquotino != 0 && mp->m_sb.sb_pquotino != NULLFSINO)
have_pquotino = 1;
}
if (xfs_has_align(mp)) {
fs_aligned_inodes = 1;
fs_ino_alignment = mp->m_sb.sb_inoalignmt;
}
/*
* calculate maximum file offset for this geometry
*/
fs_max_file_offset = 0x7fffffffffffffffLL >> mp->m_sb.sb_blocklog;
return(0);
}