xfsprogs/0053-mkfs-enable-the-new-force-align-feature.patch
zhangjian f908c320a1 support atomic write
(cherry picked from commit 40226fa996b6e2d02ded47834cf5289a5f7160e6)
2024-06-19 11:40:47 +08:00

315 lines
8.9 KiB
Diff

From 2c0500e6036dc996ea9553c9d56b26f54d815e45 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Fri, 29 Sep 2023 09:53:42 +0000
Subject: [PATCH 07/11] mkfs: enable the new force-align feature
Make it so that we can create filesystems with the forcealign feature
turned on.
jpg: enforce extsize must be a power-of-2 for forcealign, relocate
is_power_of_2() to be accessible for mkfs
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
include/libxfs.h | 6 +++
libxfs/libxfs_priv.h | 6 ---
man/man8/mkfs.xfs.8 | 15 ++++++
mkfs/xfs_mkfs.c | 124 ++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 143 insertions(+), 8 deletions(-)
diff --git a/include/libxfs.h b/include/libxfs.h
index 24424d0..cf4baff 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -43,6 +43,12 @@ struct iomap;
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
#define unlikely(x) (x)
+static inline __attribute__((const))
+int is_power_of_2(unsigned long n)
+{
+ return (n != 0 && ((n & (n - 1)) == 0));
+}
+
/*
* This mirrors the kernel include for xfs_buf.h - it's implicitly included in
* every files via a similar include in the kernel xfs_linux.h.
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index 15bae1f..0dc6627 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h
@@ -369,12 +369,6 @@ find_next_zero_bit(const unsigned long *addr, unsigned long size,
}
#define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
-static inline __attribute__((const))
-int is_power_of_2(unsigned long n)
-{
- return (n != 0 && ((n & (n - 1)) == 0));
-}
-
/*
* xfs_iroundup: round up argument to next power of two
*/
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index 5cd69fa..8f159a4 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -654,6 +654,21 @@ space over time such that no free extents are large enough to
accommodate a chunk of 64 inodes. Without this feature enabled, inode
allocations can fail with out of space errors under severe fragmented
free space conditions.
+.TP
+.BI forcealign[= value]
+If
+.B value
+is 1, mark the root directory so that all file data extent allocations will be
+aligned to the extent size hint.
+These allocations will be mapped into the file range at offsets that are
+aligned to the extent size hint.
+The
+.B extszinherit
+option must be specified.
+The
+.B cowextsize
+option must not be specified.
+This feature is only available for filesystems formatted with -m crc=1.
.RE
.PP
.PD 0
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index fb0c53f..1253ece 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -81,6 +81,7 @@ enum {
I_ATTR,
I_PROJID32BIT,
I_SPINODES,
+ I_FORCEALIGN,
I_MAX_OPTS,
};
@@ -451,6 +452,7 @@ static struct opt_params iopts = {
[I_ATTR] = "attr",
[I_PROJID32BIT] = "projid32bit",
[I_SPINODES] = "sparse",
+ [I_FORCEALIGN] = "forcealign",
[I_MAX_OPTS] = NULL,
},
.subopt_params = {
@@ -500,6 +502,12 @@ static struct opt_params iopts = {
.maxval = 1,
.defaultval = 1,
},
+ { .index = I_FORCEALIGN,
+ .conflicts = { { NULL, LAST_CONFLICT } },
+ .minval = 0,
+ .maxval = 1,
+ .defaultval = 1,
+ },
},
};
@@ -829,6 +837,7 @@ struct sb_feat_args {
bool bigtime; /* XFS_SB_FEAT_INCOMPAT_BIGTIME */
bool nodalign;
bool nortalign;
+ bool forcealign; /* XFS_SB_FEAT_RO_COMPAT_FORCEALIGN */
};
struct cli_params {
@@ -961,6 +970,7 @@ usage( void )
/* force overwrite */ [-f]\n\
/* inode size */ [-i perblock=n|size=num,maxpct=n,attr=0|1|2,\n\
projid32bit=0|1,sparse=0|1]\n\
+ forcealign=0|1\n\
/* no discard */ [-K]\n\
/* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx,version=n\n\
sunit=value|su=num,sectsize=num,lazy-count=0|1]\n\
@@ -1601,6 +1611,8 @@ inode_opts_parser(
const char *value,
struct cli_params *cli)
{
+ long long val;
+
switch (subopt) {
case I_ALIGN:
cli->sb_feat.inode_align = getnum(value, opts, subopt);
@@ -1623,6 +1635,17 @@ inode_opts_parser(
case I_SPINODES:
cli->sb_feat.spinodes = getnum(value, opts, subopt);
break;
+ case I_FORCEALIGN:
+ val = getnum(value, opts, subopt);
+
+ if (val == 1) {
+ cli->sb_feat.forcealign = true;
+ cli->fsx.fsx_xflags |= FS_XFLAG_FORCEALIGN;
+ } else {
+ cli->sb_feat.forcealign = false;
+ cli->fsx.fsx_xflags &= ~FS_XFLAG_FORCEALIGN;
+ }
+ break;
default:
return -EINVAL;
}
@@ -2228,6 +2251,13 @@ _("timestamps later than 2038 not supported without CRC support\n"));
usage();
}
cli->sb_feat.bigtime = false;
+
+ if (cli->sb_feat.forcealign) {
+ fprintf(stderr,
+_("forced file data alignment not supported without CRC support\n"));
+ usage();
+ }
+ cli->sb_feat.forcealign = false;
}
if (!cli->sb_feat.finobt) {
@@ -2262,6 +2292,13 @@ _("cowextsize not supported without reflink support\n"));
usage();
}
+ if ((cli->fsx.fsx_xflags & FS_XFLAG_FORCEALIGN) &&
+ (cli->fsx.fsx_cowextsize > 0 || cli->fsx.fsx_extsize == 0 || !is_power_of_2(cli->fsx.fsx_extsize))) {
+ fprintf(stderr,
+_("forcealign requires a non-zero power-of-2 extent size hint and no cow extent size hint\n"));
+ usage();
+ }
+
/*
* Copy features across to config structure now.
*/
@@ -2511,6 +2548,34 @@ _("illegal CoW extent size hint %lld, must be less than %u.\n"),
}
}
+/* Validate the incoming forcealign flag. */
+static void
+validate_forcealign(
+ struct xfs_mount *mp,
+ struct cli_params *cli)
+{
+ if (!(cli->fsx.fsx_xflags & FS_XFLAG_FORCEALIGN))
+ return;
+
+ if (cli->fsx.fsx_cowextsize != 0) {
+ fprintf(stderr,
+_("cannot set CoW extent size hint when forcealign is set.\n"));
+ usage();
+ }
+
+ if (cli->fsx.fsx_extsize == 0) {
+ fprintf(stderr,
+_("cannot set forcealign without an extent size hint.\n"));
+ usage();
+ }
+
+ if (cli->fsx.fsx_xflags & (FS_XFLAG_REALTIME | FS_XFLAG_RTINHERIT)) {
+ fprintf(stderr,
+_("cannot set forcealign and realtime flags.\n"));
+ usage();
+ }
+}
+
/*
* Validate the configured stripe geometry, or is none is specified, pull
* the configuration from the underlying device.
@@ -2978,11 +3043,63 @@ _("agsize (%s) not a multiple of fs blk size (%d)\n"),
*/
static void
align_ag_geometry(
- struct mkfs_params *cfg)
+ struct mkfs_params *cfg,
+ struct cli_params *cli)
{
uint64_t tmp_agsize;
int dsunit = cfg->dsunit;
+ /*
+ * If the sysadmin wants to force all file data space mappings to be
+ * aligned to the extszinherit value, then we need the AGs to be
+ * aligned to the same value. Skip these checks if the extent size
+ * hint is zero; the extszinherit validation will fail the format
+ * later.
+ */
+ if (cli->sb_feat.forcealign && cli->fsx.fsx_extsize != 0) {
+ /* Perfect alignment; we're done. */
+ if (cfg->agsize % cli->fsx.fsx_extsize == 0)
+ goto validate;
+
+ /*
+ * Round up to file extent size boundary. Make sure that
+ * agsize is still larger than XFS_AG_MIN_BLOCKS(blocklog).
+ */
+ tmp_agsize = ((cfg->agsize + cli->fsx.fsx_extsize - 1) /
+ cli->fsx.fsx_extsize) * cli->fsx.fsx_extsize;
+
+ /*
+ * Round down to file extent size boundary if rounding up
+ * created an AG size that is larger than the AG max.
+ */
+ if (tmp_agsize > XFS_AG_MAX_BLOCKS(cfg->blocklog))
+ tmp_agsize = (cfg->agsize / cli->fsx.fsx_extsize) *
+ cli->fsx.fsx_extsize;
+
+ if (tmp_agsize < XFS_AG_MIN_BLOCKS(cfg->blocklog) &&
+ tmp_agsize > XFS_AG_MAX_BLOCKS(cfg->blocklog)) {
+ /*
+ * Set the agsize to the invalid value so the following
+ * validation of the ag will fail and print a nice error
+ * and exit.
+ */
+ cfg->agsize = tmp_agsize;
+ goto validate;
+ }
+
+ /* Update geometry to be file extent size aligned */
+ cfg->agsize = tmp_agsize;
+ if (!cli_opt_set(&dopts, D_AGCOUNT))
+ cfg->agcount = cfg->dblocks / cfg->agsize +
+ (cfg->dblocks % cfg->agsize != 0);
+
+ if (cli_opt_set(&dopts, D_AGSIZE))
+ fprintf(stderr,
+_("agsize rounded to %lld, extszhint = %d\n"),
+ (long long)cfg->agsize, cli->fsx.fsx_extsize);
+ goto validate;
+ }
+
if (!dsunit)
goto validate;
@@ -3202,6 +3319,8 @@ sb_set_features(
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK;
if (fp->inobtcnt)
sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_INOBTCNT;
+ if (fp->forcealign)
+ sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_FORCEALIGN;
if (fp->bigtime)
sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_BIGTIME;
@@ -4164,7 +4283,7 @@ main(
* aligns to device geometry correctly.
*/
calculate_initial_ag_geometry(&cfg, &cli);
- align_ag_geometry(&cfg);
+ align_ag_geometry(&cfg, &cli);
calculate_imaxpct(&cfg, &cli);
@@ -4187,6 +4306,7 @@ main(
/* Validate the extent size hints now that @mp is fully set up. */
validate_extsize_hint(mp, &cli);
validate_cowextsize_hint(mp, &cli);
+ validate_forcealign(mp, &cli);
/* Print the intended geometry of the fs. */
if (!quiet || dry_run) {
--
2.33.0