/* * 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; }
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; }
/* * 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); }
void update_sb_version(xfs_mount_t *mp) { xfs_sb_t *sb; __uint16_t vn; sb = &mp->m_sb; if (fs_attributes && !xfs_sb_version_hasattr(sb)) { ASSERT(fs_attributes_allowed); xfs_sb_version_addattr(sb); } if (fs_attributes2 && !xfs_sb_version_hasattr2(sb)) { ASSERT(fs_attributes2_allowed); xfs_sb_version_addattr2(sb); } if (fs_inode_nlink && !xfs_sb_version_hasnlink(sb)) { ASSERT(fs_inode_nlink_allowed); xfs_sb_version_addnlink(sb); } /* * 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_sb_version_hasquota(sb)) { ASSERT(fs_quotas_allowed); xfs_sb_version_addquota(sb); } /* * protect against stray bits in the quota flag field */ if (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"), sb->sb_qflags & ~XFS_MOUNT_QUOTA_ALL); 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 { sb->sb_qflags = 0; if (xfs_sb_version_hasquota(sb)) { lost_quotas = 1; vn = sb->sb_versionnum; vn &= ~XFS_SB_VERSION_QUOTABIT; if (!(vn & XFS_SB_VERSION_ALLFBITS)) vn = xfs_sb_version_toold(vn); ASSERT(vn != 0); sb->sb_versionnum = vn; } } if (!fs_aligned_inodes && xfs_sb_version_hasalign(sb)) sb->sb_versionnum &= ~XFS_SB_VERSION_ALIGNBIT; }
/* * Mount structure initialization, provides a filled-in xfs_mount_t * such that the numerous XFS_* macros can be used. If dev is zero, * no IO will be performed (no size checks, read root inodes). */ xfs_mount_t * libxfs_mount( xfs_mount_t *mp, xfs_sb_t *sb, dev_t dev, dev_t logdev, dev_t rtdev, int flags) { xfs_daddr_t d; xfs_buf_t *bp; xfs_sb_t *sbp; int error; libxfs_buftarg_init(mp, dev, logdev, rtdev); mp->m_flags = (LIBXFS_MOUNT_32BITINODES|LIBXFS_MOUNT_32BITINOOPT); mp->m_sb = *sb; INIT_RADIX_TREE(&mp->m_perag_tree, GFP_KERNEL); sbp = &(mp->m_sb); xfs_sb_mount_common(mp, sb); xfs_alloc_compute_maxlevels(mp); xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK); xfs_ialloc_compute_maxlevels(mp); if (sbp->sb_imax_pct) { /* Make sure the maximum inode count is a multiple of the * units we allocate inodes in. */ mp->m_maxicount = (sbp->sb_dblocks * sbp->sb_imax_pct) / 100; mp->m_maxicount = ((mp->m_maxicount / mp->m_ialloc_blks) * mp->m_ialloc_blks) << sbp->sb_inopblog; } else mp->m_maxicount = 0; mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE; /* * Set whether we're using stripe alignment. */ if (xfs_sb_version_hasdalign(&mp->m_sb)) { mp->m_dalign = sbp->sb_unit; mp->m_swidth = sbp->sb_width; } /* * Set whether we're using inode alignment. */ if (xfs_sb_version_hasalign(&mp->m_sb) && mp->m_sb.sb_inoalignmt >= XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size)) mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1; else mp->m_inoalign_mask = 0; /* * If we are using stripe alignment, check whether * the stripe unit is a multiple of the inode alignment */ if (mp->m_dalign && mp->m_inoalign_mask && !(mp->m_dalign & mp->m_inoalign_mask)) mp->m_sinoalign = mp->m_dalign; else mp->m_sinoalign = 0; /* * Check that the data (and log if separate) are an ok size. */ d = (xfs_daddr_t) XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { fprintf(stderr, _("%s: size check failed\n"), progname); if (!(flags & LIBXFS_MOUNT_DEBUGGER)) return NULL; } /* * We automatically convert v1 inodes to v2 inodes now, so if * the NLINK bit is not set we can't operate on the filesystem. */ if (!(sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT)) { fprintf(stderr, _( "%s: V1 inodes unsupported. Please try an older xfsprogs.\n"), progname); exit(1); } /* Check for supported directory formats */ if (!(sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)) { fprintf(stderr, _( "%s: V1 directories unsupported. Please try an older xfsprogs.\n"), progname); exit(1); } /* check for unsupported other features */ if (!xfs_sb_good_version(sbp)) { fprintf(stderr, _( "%s: Unsupported features detected. Please try a newer xfsprogs.\n"), progname); exit(1); } xfs_da_mount(mp); if (xfs_sb_version_hasattr2(&mp->m_sb)) mp->m_flags |= LIBXFS_MOUNT_ATTR2; /* Initialize the precomputed transaction reservations values */ xfs_trans_init(mp); if (dev == 0) /* maxtrres, we have no device so leave now */ return mp; bp = libxfs_readbuf(mp->m_dev, d - XFS_FSS_TO_BB(mp, 1), XFS_FSS_TO_BB(mp, 1), !(flags & LIBXFS_MOUNT_DEBUGGER), NULL); if (!bp) { fprintf(stderr, _("%s: data size check failed\n"), progname); if (!(flags & LIBXFS_MOUNT_DEBUGGER)) return NULL; } else libxfs_putbuf(bp); if (mp->m_logdev_targp->dev && mp->m_logdev_targp->dev != mp->m_ddev_targp->dev) { d = (xfs_daddr_t) XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); if ( (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) || (!(bp = libxfs_readbuf(mp->m_logdev_targp, d - XFS_FSB_TO_BB(mp, 1), XFS_FSB_TO_BB(mp, 1), !(flags & LIBXFS_MOUNT_DEBUGGER), NULL))) ) { fprintf(stderr, _("%s: log size checks failed\n"), progname); if (!(flags & LIBXFS_MOUNT_DEBUGGER)) return NULL; } if (bp) libxfs_putbuf(bp); } /* Initialize realtime fields in the mount structure */ if (rtmount_init(mp, flags)) { fprintf(stderr, _("%s: realtime device init failed\n"), progname); return NULL; } error = libxfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); if (error) { fprintf(stderr, _("%s: perag init failed\n"), progname); exit(1); } return mp; }