From c85d383b0bb1d86c676ccf817dd22ad43b589b61 Mon Sep 17 00:00:00 2001 From: John Garry Date: Fri, 1 Mar 2024 17:40:12 +0000 Subject: [PATCH 08/11] mkfs: Add atomic writes suppport Use a command like the following to enable: /mkfs.xfs -f -i forcealign=1 -d extsize=4096 -d atomic-writes=1 /dev/sda Forcealign enablement is required, and with that a specific extent size needs to be set. And extent size of 4096B (for 4K FS block size) is acceptable. Signed-off-by: John Garry --- include/linux.h | 4 ++++ libxfs/xfs_format.h | 8 ++++++-- mkfs/xfs_mkfs.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/include/linux.h b/include/linux.h index d95365b..7f295f0 100644 --- a/include/linux.h +++ b/include/linux.h @@ -251,6 +251,10 @@ struct fsxattr { #define FS_XFLAG_FORCEALIGN 0x00020000 #endif +#ifndef FS_XFLAG_ATOMICWRITES +#define FS_XFLAG_ATOMICWRITES 0x00040000 +#endif + #ifdef HAVE_GETFSMAP # include #else diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index c2db380..1dfb11c 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -451,12 +451,14 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ #define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3) /* inobt block counts */ #define XFS_SB_FEAT_RO_COMPAT_FORCEALIGN (1 << 30) /* aligned file data extents */ +#define XFS_SB_FEAT_RO_COMPAT_ATOMICWRITES (1 << 31) /* aligned file data extents */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ XFS_SB_FEAT_RO_COMPAT_REFLINK| \ XFS_SB_FEAT_RO_COMPAT_FORCEALIGN| \ - XFS_SB_FEAT_RO_COMPAT_INOBTCNT) + XFS_SB_FEAT_RO_COMPAT_INOBTCNT| \ + XFS_SB_FEAT_RO_COMPAT_ATOMICWRITES) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL static inline bool xfs_sb_has_ro_compat_feature( @@ -1180,16 +1182,18 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) #define XFS_DIFLAG2_BIGTIME_BIT 3 /* big timestamps */ /* data extent mappings for regular files must be aligned to extent size hint */ #define XFS_DIFLAG2_FORCEALIGN_BIT 5 +#define XFS_DIFLAG2_ATOMICWRITES_BIT 6 #define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT) #define XFS_DIFLAG2_REFLINK (1 << XFS_DIFLAG2_REFLINK_BIT) #define XFS_DIFLAG2_COWEXTSIZE (1 << XFS_DIFLAG2_COWEXTSIZE_BIT) #define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT) #define XFS_DIFLAG2_FORCEALIGN (1 << XFS_DIFLAG2_FORCEALIGN_BIT) +#define XFS_DIFLAG2_ATOMICWRITES (1 << XFS_DIFLAG2_ATOMICWRITES_BIT) #define XFS_DIFLAG2_ANY \ (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \ - XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_FORCEALIGN) + XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_FORCEALIGN | XFS_DIFLAG2_ATOMICWRITES) static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) { diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 1253ece..5169255 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -70,6 +70,7 @@ enum { D_EXTSZINHERIT, D_COWEXTSIZE, D_DAXINHERIT, + D_ATOMICWRITES, D_MAX_OPTS, }; @@ -306,6 +307,7 @@ static struct opt_params dopts = { [D_EXTSZINHERIT] = "extszinherit", [D_COWEXTSIZE] = "cowextsize", [D_DAXINHERIT] = "daxinherit", + [D_ATOMICWRITES] = "atomic-writes", [D_MAX_OPTS] = NULL, }, .subopt_params = { @@ -437,6 +439,12 @@ static struct opt_params dopts = { .maxval = 1, .defaultval = 1, }, + { .index = D_ATOMICWRITES, + .conflicts = { { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, }, }; @@ -838,6 +846,7 @@ struct sb_feat_args { bool nodalign; bool nortalign; bool forcealign; /* XFS_SB_FEAT_RO_COMPAT_FORCEALIGN */ + bool atomicwrites; /* XFS_SB_FEAT_RO_COMPAT_ATOMICWRITES */ }; struct cli_params { @@ -1598,6 +1607,13 @@ data_opts_parser( else cli->fsx.fsx_xflags &= ~FS_XFLAG_DAX; break; + case D_ATOMICWRITES: + if (getnum(value, opts, subopt) == 1) { + cli->sb_feat.atomicwrites = true; + } else { + cli->sb_feat.atomicwrites = false; + } + break; default: return -EINVAL; } @@ -2557,6 +2573,12 @@ validate_forcealign( if (!(cli->fsx.fsx_xflags & FS_XFLAG_FORCEALIGN)) return; + if (cli->fsx.fsx_xflags & (FS_XFLAG_REALTIME | FS_XFLAG_RTINHERIT)) { + fprintf(stderr, +_("cannot set forcealign and realtime flags.\n")); + usage(); + } + if (cli->fsx.fsx_cowextsize != 0) { fprintf(stderr, _("cannot set CoW extent size hint when forcealign is set.\n")); @@ -2576,6 +2598,30 @@ _("cannot set forcealign and realtime flags.\n")); } } +/* Validate the incoming forcealign flag. */ +static void +validate_atomicwrites( + struct mkfs_params *cfg, + struct xfs_mount *mp, + struct cli_params *cli, + char *dfile + ) +{ + if (!cli->sb_feat.atomicwrites) + return; + + if (!(cli->fsx.fsx_xflags & FS_XFLAG_FORCEALIGN)) { + fprintf(stderr, +_("cannot set atomicwrites without forcealign.\n")); + usage(); + } + + /* + * TODO: Add a check to see if the dfile can support atomic writes of + * extsize. + */ +} + /* * Validate the configured stripe geometry, or is none is specified, pull * the configuration from the underlying device. @@ -3321,6 +3367,8 @@ sb_set_features( 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->atomicwrites) + sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_ATOMICWRITES; if (fp->bigtime) sbp->sb_features_incompat |= XFS_SB_FEAT_INCOMPAT_BIGTIME; @@ -4307,6 +4355,7 @@ main( validate_extsize_hint(mp, &cli); validate_cowextsize_hint(mp, &cli); validate_forcealign(mp, &cli); + validate_atomicwrites(&cfg, mp, &cli, dfile); /* Print the intended geometry of the fs. */ if (!quiet || dry_run) { -- 2.33.0