[PATCH 03/15] mkfs: Sanitise the superblock feature macros
Dave Chinner
david at fromorbit.com
Thu Nov 28 19:43:38 CST 2013
From: Dave Chinner <dchinner at redhat.com>
They are horrible macros that simply obfuscate the code, so
let's factor the code and make them nice functions.
To do this, add a sb_feat_args structure that carries around the
variables rather than a strange assortment of variables. This means
all the default can be clearly defined in a structure
initialisation, and dependent feature bits are easy to check.
Signed-off-by: Dave Chinner <dchinner at redhat.com>
---
include/xfs_mkfs.h | 25 +-----
mkfs/xfs_mkfs.c | 227 ++++++++++++++++++++++++++++++++++-------------------
2 files changed, 146 insertions(+), 106 deletions(-)
diff --git a/include/xfs_mkfs.h b/include/xfs_mkfs.h
index 3388f6d..3af9cb1 100644
--- a/include/xfs_mkfs.h
+++ b/include/xfs_mkfs.h
@@ -23,36 +23,13 @@
XFS_SB_VERSION_EXTFLGBIT | \
XFS_SB_VERSION_DIRV2BIT)
-#define XFS_SB_VERSION_MKFS(crc,ia,dia,log2,attr1,sflag,ci,more) (\
- ((crc)||(ia)||(dia)||(log2)||(attr1)||(sflag)||(ci)||(more)) ? \
- (((crc) ? XFS_SB_VERSION_5 : XFS_SB_VERSION_4) | \
- ((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) | \
- ((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) | \
- ((log2) ? XFS_SB_VERSION_LOGV2BIT : 0) | \
- ((attr1) ? XFS_SB_VERSION_ATTRBIT : 0) | \
- ((sflag) ? XFS_SB_VERSION_SECTORBIT : 0) | \
- ((ci) ? XFS_SB_VERSION_BORGBIT : 0) | \
- ((more) ? XFS_SB_VERSION_MOREBITSBIT : 0) | \
- XFS_DFL_SB_VERSION_BITS | \
- 0 ) : XFS_SB_VERSION_1 )
-
-#define XFS_SB_VERSION2_MKFS(crc, lazycount, attr2, projid32bit, parent, \
- ftype) (\
- ((lazycount) ? XFS_SB_VERSION2_LAZYSBCOUNTBIT : 0) | \
- ((attr2) ? XFS_SB_VERSION2_ATTR2BIT : 0) | \
- ((projid32bit) ? XFS_SB_VERSION2_PROJID32BIT : 0) | \
- ((parent) ? XFS_SB_VERSION2_PARENTBIT : 0) | \
- ((crc) ? XFS_SB_VERSION2_CRCBIT : 0) | \
- ((ftype) ? XFS_SB_VERSION2_FTYPE : 0) | \
- 0 )
-
#define XFS_DFL_BLOCKSIZE_LOG 12 /* 4096 byte blocks */
#define XFS_DINODE_DFL_LOG 8 /* 256 byte inodes */
#define XFS_DINODE_DFL_CRC_LOG 9 /* 512 byte inodes for CRCs */
#define XFS_MIN_DATA_BLOCKS 100
#define XFS_MIN_INODE_PERBLOCK 2 /* min inodes per block */
#define XFS_DFL_IMAXIMUM_PCT 25 /* max % of space for inodes */
-#define XFS_IFLAG_ALIGN 1 /* -i align defaults on */
+#define XFS_IFLAG_ALIGN true /* -i align defaults on */
#define XFS_MIN_REC_DIRSIZE 12 /* 4096 byte dirblocks (V2) */
#define XFS_DFL_DIR_VERSION 2 /* default directory version */
#define XFS_DFL_LOG_SIZE 1000 /* default log size, blocks */
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 3145205..caa0631 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -862,6 +862,86 @@ discard_blocks(dev_t dev, __uint64_t nsectors)
platform_discard_blocks(fd, 0, nsectors << 9);
}
+struct sb_feat_args {
+ int log_version;
+ int attr_version;
+ int dir_version;
+ bool inode_align;
+ bool nci;
+ bool lazy_sb_counters;
+ bool projid16bit;
+ bool crcs_enabled;
+ bool dirftype;
+ bool parent_pointers;
+};
+
+static void
+sb_set_features(
+ struct xfs_sb *sbp,
+ struct sb_feat_args *fp,
+ int sectsize,
+ int lsectsize,
+ int dsunit)
+{
+
+ sbp->sb_versionnum = XFS_DFL_SB_VERSION_BITS;
+ if (fp->crcs_enabled)
+ sbp->sb_versionnum |= XFS_SB_VERSION_5;
+ else
+ sbp->sb_versionnum |= XFS_SB_VERSION_4;
+
+ if (fp->inode_align)
+ sbp->sb_versionnum |= XFS_SB_VERSION_ALIGNBIT;
+ if (dsunit)
+ sbp->sb_versionnum |= XFS_SB_VERSION_DALIGNBIT;
+ if (fp->log_version == 2)
+ sbp->sb_versionnum |= XFS_SB_VERSION_LOGV2BIT;
+ if (fp->attr_version == 1)
+ sbp->sb_versionnum |= XFS_SB_VERSION_ATTRBIT;
+ if (sectsize > BBSIZE || lsectsize > BBSIZE)
+ sbp->sb_versionnum |= XFS_SB_VERSION_SECTORBIT;
+ if (fp->nci)
+ sbp->sb_versionnum |= XFS_SB_VERSION_BORGBIT;
+
+
+ sbp->sb_features2 = 0;
+ if (fp->lazy_sb_counters)
+ sbp->sb_features2 |= XFS_SB_VERSION2_LAZYSBCOUNTBIT;
+ if (!fp->projid16bit)
+ sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT;
+ if (fp->parent_pointers)
+ sbp->sb_features2 |= XFS_SB_VERSION2_PARENTBIT;
+ if (fp->crcs_enabled)
+ sbp->sb_features2 |= XFS_SB_VERSION2_CRCBIT;
+ if (fp->attr_version == 2)
+ sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT;
+
+ /* v5 superblocks have their own feature bit for dirftype */
+ if (fp->dirftype && !fp->crcs_enabled)
+ sbp->sb_features2 |= XFS_SB_VERSION2_FTYPE;
+
+ /* update whether extended features are in use */
+ if (sbp->sb_features2 != 0)
+ sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;
+
+ /*
+ * Due to a structure alignment issue, sb_features2 ended up in one
+ * of two locations, the second "incorrect" location represented by
+ * the sb_bad_features2 field. To avoid older kernels mounting
+ * filesystems they shouldn't, set both field to the same value.
+ */
+ sbp->sb_bad_features2 = sbp->sb_features2;
+
+ if (!fp->crcs_enabled)
+ return;
+
+ /* default features for v5 filesystems */
+ sbp->sb_features_compat = 0;
+ sbp->sb_features_ro_compat = 0;
+ sbp->sb_features_incompat = XFS_SB_FEAT_INCOMPAT_FTYPE;
+ sbp->sb_features_log_incompat = 0;
+}
+
int
main(
int argc,
@@ -873,8 +953,6 @@ main(
xfs_agnumber_t agno;
__uint64_t agsize;
xfs_alloc_rec_t *arec;
- int attrversion;
- int projid16bit;
struct xfs_btree_block *block;
int blflag;
int blocklog;
@@ -889,8 +967,6 @@ main(
char *dfile;
int dirblocklog;
int dirblocksize;
- int dirftype;
- int dirversion;
char *dsize;
int dsu;
int dsw;
@@ -898,7 +974,6 @@ main(
int dswidth;
int force_overwrite;
struct fsxattr fsx;
- int iaflag;
int ilflag;
int imaxpct;
int imflag;
@@ -918,7 +993,6 @@ main(
int loginternal;
char *logsize;
xfs_dfsbno_t logstart;
- int logversion;
int lvflag;
int lsflag;
int lsectorlog;
@@ -938,7 +1012,6 @@ main(
int nftype;
int nsflag;
int nvflag;
- int nci;
int Nflag;
int discard = 1;
char *p;
@@ -962,16 +1035,24 @@ main(
int worst_freelist;
libxfs_init_t xi;
struct fs_topology ft;
- int lazy_sb_counters;
- int crcs_enabled;
+ struct sb_feat_args sb_feat = {
+ .log_version = 2,
+ .attr_version = 2,
+ .dir_version = XFS_DFL_DIR_VERSION,
+ .inode_align = XFS_IFLAG_ALIGN,
+ .nci = false,
+ .lazy_sb_counters = true,
+ .projid16bit = false,
+ .crcs_enabled = false,
+ .dirftype = false,
+ .parent_pointers = false,
+ };
progname = basename(argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- attrversion = 2;
- projid16bit = 0;
blflag = bsflag = slflag = ssflag = lslflag = lssflag = 0;
blocklog = blocksize = 0;
sectorlog = lsectorlog = XFS_MIN_SECTORSIZE_LOG;
@@ -980,23 +1061,18 @@ main(
ilflag = imflag = ipflag = isflag = 0;
liflag = laflag = lsflag = ldflag = lvflag = 0;
loginternal = 1;
- logversion = 2;
logagno = logblocks = rtblocks = rtextblocks = 0;
- Nflag = nlflag = nsflag = nvflag = nci = 0;
- nftype = dirftype = 0; /* inode type information in the dir */
+ Nflag = nlflag = nsflag = nvflag = 0;
+ nftype = 0;
dirblocklog = dirblocksize = 0;
- dirversion = XFS_DFL_DIR_VERSION;
qflag = 0;
imaxpct = inodelog = inopblock = isize = 0;
- iaflag = XFS_IFLAG_ALIGN;
dfile = logfile = rtfile = NULL;
dsize = logsize = rtsize = rtextsize = protofile = NULL;
dsu = dsw = dsunit = dswidth = lalign = lsu = lsunit = 0;
nodsflag = norsflag = 0;
force_overwrite = 0;
worst_freelist = 0;
- lazy_sb_counters = 1;
- crcs_enabled = 0;
memset(&fsx, 0, sizeof(fsx));
memset(&xi, 0, sizeof(xi));
@@ -1235,10 +1311,11 @@ main(
switch (getsubopt(&p, (constpp)iopts, &value)) {
case I_ALIGN:
if (!value || *value == '\0')
- value = "1";
- iaflag = atoi(value);
- if (iaflag < 0 || iaflag > 1)
+ break;
+ c = atoi(value);
+ if (c < 0 || c > 1)
illegal(value, "i align");
+ sb_feat.inode_align = c ? true : false;
break;
case I_LOG:
if (!value || *value == '\0')
@@ -1308,7 +1385,7 @@ main(
c = atoi(value);
if (c < 0 || c > 2)
illegal(value, "i attr");
- attrversion = c;
+ sb_feat.attr_version = c;
break;
case I_PROJID32BIT:
if (!value || *value == '\0')
@@ -1316,7 +1393,7 @@ main(
c = atoi(value);
if (c < 0 || c > 1)
illegal(value, "i projid32bit");
- projid16bit = c ? 0 : 1;
+ sb_feat.projid16bit = c ? false : true;
break;
default:
unknown('i', value);
@@ -1406,9 +1483,10 @@ main(
reqval('l', lopts, L_VERSION);
if (lvflag)
respec('l', lopts, L_VERSION);
- logversion = atoi(value);
- if (logversion < 1 || logversion > 2)
+ c = atoi(value);
+ if (c < 1 || c > 2)
illegal(value, "l version");
+ sb_feat.log_version = c;
lvflag = 1;
break;
case L_SIZE:
@@ -1457,7 +1535,8 @@ main(
c = atoi(value);
if (c < 0 || c > 1)
illegal(value, "l lazy-count");
- lazy_sb_counters = c;
+ sb_feat.lazy_sb_counters = c ? true
+ : false;
break;
default:
unknown('l', value);
@@ -1481,12 +1560,14 @@ main(
c = atoi(value);
if (c < 0 || c > 1)
illegal(value, "m crc");
- crcs_enabled = c;
- if (nftype && crcs_enabled) {
+ if (c && nftype) {
fprintf(stderr,
_("cannot specify both crc and ftype\n"));
usage();
}
+ sb_feat.crcs_enabled = c ? true : false;
+ if (c)
+ sb_feat.dirftype = true;
break;
default:
unknown('m', value);
@@ -1536,12 +1617,14 @@ _("cannot specify both crc and ftype\n"));
if (nvflag)
respec('n', nopts, N_VERSION);
if (!strcasecmp(value, "ci")) {
- nci = 1; /* ASCII CI mode */
+ /* ASCII CI mode */
+ sb_feat.nci = true;
} else {
- dirversion = atoi(value);
- if (dirversion != 2)
+ c = atoi(value);
+ if (c != 2)
illegal(value,
"n version");
+ sb_feat.dir_version = c;
}
nvflag = 1;
break;
@@ -1553,12 +1636,12 @@ _("cannot specify both crc and ftype\n"));
c = atoi(value);
if (c < 0 || c > 1)
illegal(value, "n ftype");
- if (crcs_enabled) {
+ if (sb_feat.crcs_enabled) {
fprintf(stderr,
_("cannot specify both crc and ftype\n"));
usage();
}
- dirftype = c;
+ sb_feat.dirftype = c ? true : false;
nftype = 1;
break;
default:
@@ -1778,7 +1861,7 @@ _("block size %d cannot be smaller than logical sector size %d\n"),
usage();
} else if (lsectorsize > XFS_MIN_SECTORSIZE && !lsu && !lsunit) {
lsu = blocksize;
- logversion = 2;
+ sb_feat.log_version = 2;
}
/*
@@ -1786,7 +1869,7 @@ _("block size %d cannot be smaller than logical sector size %d\n"),
* no longer optional for CRC enabled filesystems. Catch them up front
* here before doing anything else.
*/
- if (crcs_enabled) {
+ if (sb_feat.crcs_enabled) {
/* minimum inode size is 512 bytes, ipflag checked later */
if ((isflag || ilflag) && inodelog < XFS_DINODE_DFL_CRC_LOG) {
fprintf(stderr,
@@ -1796,28 +1879,28 @@ _("Minimum inode size for CRCs is %d bytes\n"),
}
/* inodes always aligned */
- if (iaflag != 1) {
+ if (!sb_feat.inode_align) {
fprintf(stderr,
_("Inodes always aligned for CRC enabled filesytems\n"));
usage();
}
/* lazy sb counters always on */
- if (lazy_sb_counters != 1) {
+ if (!sb_feat.lazy_sb_counters) {
fprintf(stderr,
_("Lazy superblock counted always enabled for CRC enabled filesytems\n"));
usage();
}
/* version 2 logs always on */
- if (logversion != 2) {
+ if (sb_feat.log_version != 2) {
fprintf(stderr,
_("V2 logs always enabled for CRC enabled filesytems\n"));
usage();
}
/* attr2 always on */
- if (attrversion != 2) {
+ if (sb_feat.attr_version != 2) {
fprintf(stderr,
_("V2 attribute format always enabled on CRC enabled filesytems\n"));
usage();
@@ -1825,7 +1908,7 @@ _("V2 attribute format always enabled on CRC enabled filesytems\n"));
/* 32 bit project quota always on */
/* attr2 always on */
- if (projid16bit == 1) {
+ if (sb_feat.projid16bit) {
fprintf(stderr,
_("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
usage();
@@ -1879,11 +1962,11 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
inodelog = blocklog - libxfs_highbit32(inopblock);
isize = 1 << inodelog;
} else if (!ilflag && !isflag) {
- inodelog = crcs_enabled ? XFS_DINODE_DFL_CRC_LOG
- : XFS_DINODE_DFL_LOG;
+ inodelog = sb_feat.crcs_enabled ? XFS_DINODE_DFL_CRC_LOG
+ : XFS_DINODE_DFL_LOG;
isize = 1 << inodelog;
}
- if (crcs_enabled && inodelog < XFS_DINODE_DFL_CRC_LOG) {
+ if (sb_feat.crcs_enabled && inodelog < XFS_DINODE_DFL_CRC_LOG) {
fprintf(stderr,
_("Minimum inode size for CRCs is %d bytes\n"),
1 << XFS_DINODE_DFL_CRC_LOG);
@@ -2015,10 +2098,10 @@ _("32 bit Project IDs always enabled on CRC enabled filesytems\n"));
}
/* if lsu or lsunit was specified, automatically use v2 logs */
- if ((lsu || lsunit) && logversion == 1) {
+ if ((lsu || lsunit) && sb_feat.log_version == 1) {
fprintf(stderr,
_("log stripe unit specified, using v2 logs\n"));
- logversion = 2;
+ sb_feat.log_version = 2;
}
calc_stripe_factors(dsu, dsw, sectorsize, lsu, lsectorsize,
@@ -2333,12 +2416,12 @@ an AG size that is one stripe unit smaller, for example %llu.\n"),
}
/* convert from 512 byte blocks to fs blocks */
lsunit = DTOBT(lsunit);
- } else if (logversion == 2 && loginternal && dsunit) {
+ } else if (sb_feat.log_version == 2 && loginternal && dsunit) {
/* lsunit and dsunit now in fs blocks */
lsunit = dsunit;
}
- if (logversion == 2 && (lsunit * blocksize) > 256 * 1024) {
+ if (sb_feat.log_version == 2 && (lsunit * blocksize) > 256 * 1024) {
fprintf(stderr,
_("log stripe unit (%d bytes) is too large (maximum is 256KiB)\n"),
(lsunit * blocksize));
@@ -2346,9 +2429,9 @@ an AG size that is one stripe unit smaller, for example %llu.\n"),
fprintf(stderr, _("log stripe unit adjusted to 32KiB\n"));
}
- min_logblocks = max_trans_res(crcs_enabled, dirversion,
+ min_logblocks = max_trans_res(sb_feat.crcs_enabled, sb_feat.dir_version,
sectorlog, blocklog, inodelog, dirblocklog,
- logversion, lsunit);
+ sb_feat.log_version, lsunit);
ASSERT(min_logblocks);
min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks);
if (!logsize && dblocks >= (1024*1024*1024) >> blocklog)
@@ -2462,14 +2545,6 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
}
validate_log_size(logblocks, blocklog, min_logblocks);
- /*
- * dirent filetype field always enabled on v5 superblocks
- */
- if (crcs_enabled) {
- sbp->sb_features_incompat = XFS_SB_FEAT_INCOMPAT_FTYPE;
- dirftype = 1;
- }
-
if (!qflag || Nflag) {
printf(_(
"meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n"
@@ -2482,13 +2557,16 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
" =%-22s sectsz=%-5u sunit=%d blks, lazy-count=%d\n"
"realtime =%-22s extsz=%-6d blocks=%lld, rtextents=%lld\n"),
dfile, isize, (long long)agcount, (long long)agsize,
- "", sectorsize, attrversion, !projid16bit,
- "", crcs_enabled,
+ "", sectorsize, sb_feat.attr_version,
+ !sb_feat.projid16bit,
+ "", sb_feat.crcs_enabled,
"", blocksize, (long long)dblocks, imaxpct,
"", dsunit, dswidth,
- dirversion, dirblocksize, nci, dirftype,
+ sb_feat.dir_version, dirblocksize, sb_feat.nci,
+ sb_feat.dirftype,
logfile, 1 << blocklog, (long long)logblocks,
- logversion, "", lsectorsize, lsunit, lazy_sb_counters,
+ sb_feat.log_version, "", lsectorsize, lsunit,
+ sb_feat.lazy_sb_counters,
rtfile, rtextblocks << blocklog,
(long long)rtblocks, (long long)rtextents);
if (Nflag)
@@ -2531,17 +2609,17 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
sbp->sb_unit = dsunit;
sbp->sb_width = dswidth;
sbp->sb_dirblklog = dirblocklog - blocklog;
- if (logversion == 2) { /* This is stored in bytes */
+ if (sb_feat.log_version == 2) { /* This is stored in bytes */
lsunit = (lsunit == 0) ? 1 : XFS_FSB_TO_B(mp, lsunit);
sbp->sb_logsunit = lsunit;
} else
sbp->sb_logsunit = 0;
- if (iaflag) {
+ if (sb_feat.inode_align) {
int cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
- if (crcs_enabled)
+ if (sb_feat.crcs_enabled)
cluster_size *= isize / XFS_DINODE_MIN_SIZE;
sbp->sb_inoalignmt = cluster_size >> blocklog;
- iaflag = sbp->sb_inoalignmt != 0;
+ sb_feat.inode_align = sbp->sb_inoalignmt != 0;
} else
sbp->sb_inoalignmt = 0;
if (lsectorsize != BBSIZE || sectorsize != BBSIZE) {
@@ -2552,22 +2630,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
sbp->sb_logsectsize = 0;
}
- sbp->sb_features2 = XFS_SB_VERSION2_MKFS(crcs_enabled, lazy_sb_counters,
- attrversion == 2, !projid16bit, 0,
- (!crcs_enabled && dirftype));
- sbp->sb_versionnum = XFS_SB_VERSION_MKFS(crcs_enabled, iaflag,
- dsunit != 0,
- logversion == 2, attrversion == 1,
- (sectorsize != BBSIZE ||
- lsectorsize != BBSIZE),
- nci, sbp->sb_features2 != 0);
- /*
- * Due to a structure alignment issue, sb_features2 ended up in one
- * of two locations, the second "incorrect" location represented by
- * the sb_bad_features2 field. To avoid older kernels mounting
- * filesystems they shouldn't, set both field to the same value.
- */
- sbp->sb_bad_features2 = sbp->sb_features2;
+ sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit);
if (force_overwrite)
zero_old_xfs_structures(&xi, sbp);
@@ -2623,7 +2686,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"),
libxfs_log_clear(mp->m_logdev_targp,
XFS_FSB_TO_DADDR(mp, logstart),
(xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
- &sbp->sb_uuid, logversion, lsunit, XLOG_FMT);
+ &sbp->sb_uuid, sb_feat.log_version, lsunit, XLOG_FMT);
mp = libxfs_mount(mp, sbp, xi.ddev, xi.logdev, xi.rtdev, 0);
if (mp == NULL) {
--
1.8.4.rc3
More information about the xfs
mailing list