Exemple #1
0
/*
 * XXX: this only supports reading and writing to version 4 superblock fields.
 * V5 superblocks always define certain V4 feature bits - they are blocked from
 * being changed if a V5 sb is detected, but otherwise v5 superblock features
 * are not handled here.
 */
static int
version_f(
	int		argc,
	char		**argv)
{
	__uint16_t	version = 0;
	__uint32_t	features = 0;
	xfs_agnumber_t	ag;

	if (argc == 2) {	/* WRITE VERSION */

		if ((x.isreadonly & LIBXFS_ISREADONLY) || !expert_mode) {
			dbprintf(_("%s: not in expert mode, writing disabled\n"),
				progname);
			return 0;
		}

		/* Logic here derived from the IRIX xfs_chver(1M) script. */
		if (!strcasecmp(argv[1], "extflg")) {
			switch (XFS_SB_VERSION_NUM(&mp->m_sb)) {
			case XFS_SB_VERSION_1:
				version = 0x0004 | XFS_SB_VERSION_EXTFLGBIT;
				break;
			case XFS_SB_VERSION_2:
				version = 0x0014 | XFS_SB_VERSION_EXTFLGBIT;
				break;
			case XFS_SB_VERSION_3:
				version = 0x0034 | XFS_SB_VERSION_EXTFLGBIT;
				break;
			case XFS_SB_VERSION_4:
				if (xfs_sb_version_hasextflgbit(&mp->m_sb))
					dbprintf(
		_("unwritten extents flag is already enabled\n"));
				else
					version = mp->m_sb.sb_versionnum |
						  XFS_SB_VERSION_EXTFLGBIT;
				break;
			case XFS_SB_VERSION_5:
				dbprintf(
		_("unwritten extents always enabled for v5 superblocks.\n"));
				break;
			}
		} else if (!strcasecmp(argv[1], "log2")) {
			switch (XFS_SB_VERSION_NUM(&mp->m_sb)) {
			case XFS_SB_VERSION_1:
				version = 0x0004 | XFS_SB_VERSION_LOGV2BIT;
				break;
			case XFS_SB_VERSION_2:
				version = 0x0014 | XFS_SB_VERSION_LOGV2BIT;
				break;
			case XFS_SB_VERSION_3:
				version = 0x0034 | XFS_SB_VERSION_LOGV2BIT;
				break;
			case XFS_SB_VERSION_4:
				if (xfs_sb_version_haslogv2(&mp->m_sb))
					dbprintf(
		_("version 2 log format is already in use\n"));
				else
					version = mp->m_sb.sb_versionnum |
						  XFS_SB_VERSION_LOGV2BIT;
				break;
			case XFS_SB_VERSION_5:
				dbprintf(
		_("Version 2 logs always enabled for v5 superblocks.\n"));
				break;
			}
		} else if (XFS_SB_VERSION_NUM(&mp->m_sb) == XFS_SB_VERSION_5) {
			dbprintf(
		_("%s: Cannot change %s on v5 superblocks.\n"),
				progname, argv[1]);
			return 0;
		} else if (!strcasecmp(argv[1], "attr1")) {

			if (xfs_sb_version_hasattr2(&mp->m_sb)) {
				if (!(mp->m_sb.sb_features2 &=
						~XFS_SB_VERSION2_ATTR2BIT))
					mp->m_sb.sb_versionnum &=
						~XFS_SB_VERSION_MOREBITSBIT;
			}
			xfs_sb_version_addattr(&mp->m_sb);
			version = mp->m_sb.sb_versionnum;
			features = mp->m_sb.sb_features2;
		} else if (!strcasecmp(argv[1], "attr2")) {
			xfs_sb_version_addattr(&mp->m_sb);
			xfs_sb_version_addattr2(&mp->m_sb);
			version = mp->m_sb.sb_versionnum;
			features = mp->m_sb.sb_features2;
		} else if (!strcasecmp(argv[1], "projid32bit")) {
			xfs_sb_version_addprojid32bit(&mp->m_sb);
			version = mp->m_sb.sb_versionnum;
			features = mp->m_sb.sb_features2;
		} else {
			dbprintf(_("%s: invalid version change command \"%s\"\n"),
				progname, argv[1]);
			return 0;
		}

		if (version) {
			dbprintf(_("writing all SBs\n"));
			for (ag = 0; ag < mp->m_sb.sb_agcount; ag++)
				if (!do_version(ag, version, features)) {
					dbprintf(_("failed to set versionnum "
						 "in AG %d\n"), ag);
					break;
				}
			mp->m_sb.sb_versionnum = version;
			mp->m_sb.sb_features2 = features;
		}
	}

	if (argc == 3) {	/* VERSIONNUM + FEATURES2 */
		char	*sp;

		version = mp->m_sb.sb_versionnum;
		features = mp->m_sb.sb_features2;
		mp->m_sb.sb_versionnum = strtoul(argv[1], &sp, 0);
		mp->m_sb.sb_features2 = strtoul(argv[2], &sp, 0);
	}

	dbprintf(_("versionnum [0x%x+0x%x] = %s\n"), mp->m_sb.sb_versionnum,
			mp->m_sb.sb_features2, version_string(&mp->m_sb));

	if (argc == 3) {	/* now reset... */
		mp->m_sb.sb_versionnum = version;
		mp->m_sb.sb_features2 = features;
		return 0;
	}

	return 0;
}
Exemple #2
0
static char *
version_string(
	xfs_sb_t	*sbp)
{
	static char	s[1024];

	if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_1)
		strcpy(s, "V1");
	else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_2)
		strcpy(s, "V2");
	else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_3)
		strcpy(s, "V3");
	else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4)
		strcpy(s, "V4");
	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_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_haslogv2(sbp))
		strcat(s, ",LOGV2");
	if (xfs_sb_version_hasextflgbit(sbp))
		strcat(s, ",EXTFLG");
	if (xfs_sb_version_hassector(sbp))
		strcat(s, ",SECTOR");
	if (xfs_sb_version_hasasciici(sbp))
		strcat(s, ",ASCII_CI");
	if (xfs_sb_version_hasmorebits(sbp))
		strcat(s, ",MOREBITS");
	if (xfs_sb_version_hasattr2(sbp))
		strcat(s, ",ATTR2");
	if (xfs_sb_version_haslazysbcount(sbp))
		strcat(s, ",LAZYSBCOUNT");
	if (xfs_sb_version_hasprojid32bit(sbp))
		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");
	return s;
}
Exemple #3
0
/*
 * 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(xfs_sb_t *sb)
{
	int issue_warning;

	fs_attributes = 0;
	fs_attributes2 = 0;
	fs_inode_nlink = 0;
	fs_quotas = 0;
	fs_aligned_inodes = 0;
	fs_sb_feature_bits = 0;
	fs_ino_alignment = 0;
	fs_has_extflgbit = 0;
	have_uquotino = 0;
	have_gquotino = 0;
	have_pquotino = 0;
	issue_warning = 0;

	/*
	 * ok, check to make sure that the sb isn't newer
	 * than we are
	 */
	if (xfs_sb_version_hasextflgbit(sb))  {
		fs_has_extflgbit = 1;
		if (!fs_has_extflgbit_allowed)  {
			issue_warning = 1;
			do_warn(
			_("This filesystem has uninitialized extent flags.\n"));
		}
	}

	if (xfs_sb_version_hasshared(sb))  {
		fs_shared = 1;
		if (!fs_shared_allowed)  {
			issue_warning = 1;
			do_warn(_("This filesystem is marked shared.\n"));
		}
	}

	if (issue_warning)  {
		do_warn(
_("This filesystem uses feature(s) not yet supported in this release.\n"
  "Please run a more recent version of xfs_repair.\n"));
		return(1);
	}

	if (!xfs_sb_good_version(sb))  {
		do_warn(_("WARNING:  unknown superblock version %d\n"),
			XFS_SB_VERSION_NUM(sb));
		do_warn(
_("This filesystem contains features not understood by this program.\n"));
		return(1);
	}

	if (XFS_SB_VERSION_NUM(sb) >= XFS_SB_VERSION_4)  {
		if (!fs_sb_feature_bits_allowed)  {
			if (!no_modify)  {
				do_warn(
_("WARNING:  you have disallowed superblock-feature-bits-allowed\n"
  "\tbut this superblock has feature bits.  The superblock\n"
  "\twill be downgraded.  This may cause loss of filesystem meta-data\n"));
			} else   {
				do_warn(
_("WARNING:  you have disallowed superblock-feature-bits-allowed\n"
  "\tbut this superblock has feature bits.  The superblock\n"
  "\twould be downgraded.  This might cause loss of filesystem\n"
  "\tmeta-data.\n"));
			}
		} else   {
			fs_sb_feature_bits = 1;
		}
	}

	if (xfs_sb_version_hasattr(sb))  {
		if (!fs_attributes_allowed)  {
			if (!no_modify)  {
				do_warn(
_("WARNING:  you have disallowed attributes but this filesystem\n"
  "\thas attributes.  The filesystem will be downgraded and\n"
  "\tall attributes will be removed.\n"));
			} else  {
				do_warn(
_("WARNING:  you have disallowed attributes but this filesystem\n"
  "\thas attributes.  The filesystem would be downgraded and\n"
  "\tall attributes would be removed.\n"));
			}
		} else   {
			fs_attributes = 1;
		}
	}

	if (xfs_sb_version_hasattr2(sb))  {
		if (!fs_attributes2_allowed)  {
			if (!no_modify)  {
				do_warn(
_("WARNING:  you have disallowed attr2 attributes but this filesystem\n"
  "\thas attributes.  The filesystem will be downgraded and\n"
  "\tall attr2 attributes will be removed.\n"));
			} else  {
				do_warn(
_("WARNING:  you have disallowed attr2 attributes but this filesystem\n"
  "\thas attributes.  The filesystem would be downgraded and\n"
  "\tall attr2 attributes would be removed.\n"));
			}
		} else   {
			fs_attributes2 = 1;
		}
	}

	if (xfs_sb_version_hasnlink(sb))  {
		if (!fs_inode_nlink_allowed)  {
			if (!no_modify)  {
				do_warn(
_("WARNING:  you have disallowed version 2 inodes but this filesystem\n"
  "\thas version 2 inodes.  The filesystem will be downgraded and\n"
  "\tall version 2 inodes will be converted to version 1 inodes.\n"
  "\tThis may cause some hard links to files to be destroyed\n"));
			} else  {
				do_warn(
_("WARNING:  you have disallowed version 2 inodes but this filesystem\n"
  "\thas version 2 inodes.  The filesystem would be downgraded and\n"
  "\tall version 2 inodes would be converted to version 1 inodes.\n"
  "\tThis might cause some hard links to files to be destroyed\n"));
			}
		} else   {
			fs_inode_nlink = 1;
		}
	}

	if (xfs_sb_version_hasquota(sb))  {
		if (!fs_quotas_allowed)  {
			if (!no_modify)  {
				do_warn(
_("WARNING:  you have disallowed quotas but this filesystem\n"
  "\thas quotas.  The filesystem will be downgraded and\n"
  "\tall quota information will be removed.\n"));
			} else  {
				do_warn(
_("WARNING:  you have disallowed quotas but this filesystem\n"
  "\thas quotas.  The filesystem would be downgraded and\n"
  "\tall quota information would be removed.\n"));
			}
		} else   {
			fs_quotas = 1;

			if (sb->sb_uquotino != 0 &&
					sb->sb_uquotino != NULLFSINO)
				have_uquotino = 1;

			if (sb->sb_gquotino != 0 &&
					sb->sb_gquotino != NULLFSINO)
				have_gquotino = 1;

			if (sb->sb_pquotino != 0 &&
					sb->sb_pquotino != NULLFSINO)
				have_pquotino = 1;
		}
	}

	if (xfs_sb_version_hasalign(sb))  {
		if (fs_aligned_inodes_allowed)  {
			fs_aligned_inodes = 1;
			fs_ino_alignment = sb->sb_inoalignmt;
		} else   {
			if (!no_modify)  {
				do_warn(
_("WARNING:  you have disallowed aligned inodes but this filesystem\n"
  "\thas aligned inodes.  The filesystem will be downgraded.\n"
  "\tThis will permanently degrade the performance of this filesystem.\n"));
			} else  {
				do_warn(
_("WARNING:  you have disallowed aligned inodes but this filesystem\n"
  "\thas aligned inodes.  The filesystem would be downgraded.\n"
  "\tThis would permanently degrade the performance of this filesystem.\n"));
			}
		}
	}

	/*
	 * calculate maximum file offset for this geometry
	 */
	fs_max_file_offset = 0x7fffffffffffffffLL >> sb->sb_blocklog;

	return(0);
}
Exemple #4
0
int
xfs_sb_version_num(xfs_sb_t *sbp)
{
    return XFS_SB_VERSION_NUM(sbp);
}
Exemple #5
0
/*
 * Check the validity of the SB found.
 */
STATIC int
xfs_mount_validate_sb(
	xfs_mount_t	*mp,
	xfs_sb_t	*sbp,
	bool		check_inprogress,
	bool		check_version)
{

	/*
	 * If the log device and data device have the
	 * same device number, the log is internal.
	 * Consequently, the sb_logstart should be non-zero.  If
	 * we have a zero sb_logstart in this case, we may be trying to mount
	 * a volume filesystem in a non-volume manner.
	 */
	if (sbp->sb_magicnum != XFS_SB_MAGIC) {
		xfs_warn(mp, "bad magic number");
		return -EWRONGFS;
	}


	if (!xfs_sb_good_version(sbp)) {
		xfs_warn(mp, "bad version");
		return -EWRONGFS;
	}

	/*
	 * Version 5 superblock feature mask validation. Reject combinations the
	 * kernel cannot support up front before checking anything else. For
	 * write validation, we don't need to check feature masks.
	 */
	if (check_version && XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) {
		if (xfs_sb_has_compat_feature(sbp,
					XFS_SB_FEAT_COMPAT_UNKNOWN)) {
			xfs_warn(mp,
"Superblock has unknown compatible features (0x%x) enabled.\n"
"Using a more recent kernel is recommended.",
				(sbp->sb_features_compat &
						XFS_SB_FEAT_COMPAT_UNKNOWN));
		}

		if (xfs_sb_has_ro_compat_feature(sbp,
					XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
			xfs_alert(mp,
"Superblock has unknown read-only compatible features (0x%x) enabled.",
				(sbp->sb_features_ro_compat &
						XFS_SB_FEAT_RO_COMPAT_UNKNOWN));
			if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
				xfs_warn(mp,
"Attempted to mount read-only compatible filesystem read-write.\n"
"Filesystem can only be safely mounted read only.");
				return -EINVAL;
			}
		}
		if (xfs_sb_has_incompat_feature(sbp,
					XFS_SB_FEAT_INCOMPAT_UNKNOWN)) {
			xfs_warn(mp,
"Superblock has unknown incompatible features (0x%x) enabled.\n"
"Filesystem can not be safely mounted by this kernel.",
				(sbp->sb_features_incompat &
						XFS_SB_FEAT_INCOMPAT_UNKNOWN));
			return -EINVAL;
		}
	}

	if (xfs_sb_version_has_pquotino(sbp)) {
		if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
			xfs_notice(mp,
			   "Version 5 of Super block has XFS_OQUOTA bits.");
			return -EFSCORRUPTED;
		}
	} else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
				XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
			xfs_notice(mp,
"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.");
			return -EFSCORRUPTED;
	}

	if (unlikely(
	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
		xfs_warn(mp,
		"filesystem is marked as having an external log; "
		"specify logdev on the mount command line.");
		return -EINVAL;
	}

	if (unlikely(
	    sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
		xfs_warn(mp,
		"filesystem is marked as having an internal log; "
		"do not specify logdev on the mount command line.");
		return -EINVAL;
	}

	/*
	 * More sanity checking.  Most of these were stolen directly from
	 * xfs_repair.
	 */
	if (unlikely(
	    sbp->sb_agcount <= 0					||
	    sbp->sb_sectsize < XFS_MIN_SECTORSIZE			||
	    sbp->sb_sectsize > XFS_MAX_SECTORSIZE			||
	    sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG			||
	    sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG			||
	    sbp->sb_sectsize != (1 << sbp->sb_sectlog)			||
	    sbp->sb_blocksize < XFS_MIN_BLOCKSIZE			||
	    sbp->sb_blocksize > XFS_MAX_BLOCKSIZE			||
	    sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG			||
	    sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG			||
	    sbp->sb_blocksize != (1 << sbp->sb_blocklog)		||
	    sbp->sb_inodesize < XFS_DINODE_MIN_SIZE			||
	    sbp->sb_inodesize > XFS_DINODE_MAX_SIZE			||
	    sbp->sb_inodelog < XFS_DINODE_MIN_LOG			||
	    sbp->sb_inodelog > XFS_DINODE_MAX_LOG			||
	    sbp->sb_inodesize != (1 << sbp->sb_inodelog)		||
	    sbp->sb_inopblock != howmany(sbp->sb_blocksize,sbp->sb_inodesize) ||
	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||
	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */)	||
	    sbp->sb_dblocks == 0					||
	    sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp)			||
	    sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp)			||
	    sbp->sb_shared_vn != 0)) {
		xfs_notice(mp, "SB sanity check failed");
		return -EFSCORRUPTED;
	}

	/*
	 * Until this is fixed only page-sized or smaller data blocks work.
	 */
	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
		xfs_warn(mp,
		"File system with blocksize %d bytes. "
		"Only pagesize (%ld) or less will currently work.",
				sbp->sb_blocksize, PAGE_SIZE);
		return -ENOSYS;
	}

	/*
	 * Currently only very few inode sizes are supported.
	 */
	switch (sbp->sb_inodesize) {
	case 256:
	case 512:
	case 1024:
	case 2048:
		break;
	default:
		xfs_warn(mp, "inode size of %d bytes not supported",
				sbp->sb_inodesize);
		return -ENOSYS;
	}

	if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
	    xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
		xfs_warn(mp,
		"file system too large to be mounted on this system.");
		return -EFBIG;
	}

	if (check_inprogress && sbp->sb_inprogress) {
		xfs_warn(mp, "Offline file system operation in progress!");
		return -EFSCORRUPTED;
	}
	return 0;
}