support atomic write

(cherry picked from commit 40226fa996b6e2d02ded47834cf5289a5f7160e6)
This commit is contained in:
zhangjian 2024-05-21 11:40:55 +08:00 committed by openeuler-sync-bot
parent 704db6b6c8
commit f908c320a1
12 changed files with 1340 additions and 2 deletions

View File

@ -0,0 +1,198 @@
From 983997ce4b8de736c5c10c33c6cf4e40076dcbdf Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Fri, 29 Sep 2023 09:53:36 +0000
Subject: [PATCH 01/11] xfs: create a new inode flag to require extsize
alignment of file data space
Conflict: m_feature is not supported in struct xfs_mount, some feature related
functions are deleted or renamed
Add a new inode flag to require that all file data extent mappings must
be aligned (both the file offset range and the allocated space itself)
to the extent size hint. Having a separate COW extent size hint is no
longer allowed.
The goal here is to enable sysadmins and users to mandate that all space
mappings in a file must have a startoff/blockcount that are aligned to
(say) a 2MB alignment and that the startblock/blockcount will follow the
same alignment.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Co-developed-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
include/linux.h | 5 +++++
include/xfs_inode.h | 5 +++++
libxfs/util.c | 2 ++
libxfs/xfs_format.h | 13 ++++++++++++-
libxfs/xfs_inode_buf.c | 40 ++++++++++++++++++++++++++++++++++++++++
libxfs/xfs_inode_buf.h | 3 +++
6 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/include/linux.h b/include/linux.h
index 2465022..d95365b 100644
--- a/include/linux.h
+++ b/include/linux.h
@@ -246,6 +246,11 @@ struct fsxattr {
#define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */
#endif
+/* data extent mappings for regular files must be aligned to extent size hint */
+#ifndef FS_XFLAG_FORCEALIGN
+#define FS_XFLAG_FORCEALIGN 0x00020000
+#endif
+
#ifdef HAVE_GETFSMAP
# include <linux/fsmap.h>
#else
diff --git a/include/xfs_inode.h b/include/xfs_inode.h
index 08a62d8..6d52a1d 100644
--- a/include/xfs_inode.h
+++ b/include/xfs_inode.h
@@ -164,6 +164,11 @@ static inline bool xfs_inode_has_bigtime(struct xfs_inode *ip)
return ip->i_diflags2 & XFS_DIFLAG2_BIGTIME;
}
+static inline bool xfs_inode_forcealign(struct xfs_inode *ip)
+{
+ return ip->i_diflags2 & XFS_DIFLAG2_FORCEALIGN;
+}
+
typedef struct cred {
uid_t cr_uid;
gid_t cr_gid;
diff --git a/libxfs/util.c b/libxfs/util.c
index 905f178..5750b3f 100644
--- a/libxfs/util.c
+++ b/libxfs/util.c
@@ -204,6 +204,8 @@ xfs_flags2diflags2(
di_flags2 |= XFS_DIFLAG2_DAX;
if (xflags & FS_XFLAG_COWEXTSIZE)
di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
+ if (xflags & FS_XFLAG_FORCEALIGN)
+ di_flags2 |= XFS_DIFLAG2_FORCEALIGN;
return di_flags2;
}
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index 37570cf..c2db380 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -450,10 +450,12 @@ xfs_sb_has_compat_feature(
#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */
#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_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)
#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL
static inline bool
@@ -586,6 +588,12 @@ static inline bool xfs_sb_version_hasinobtcounts(struct xfs_sb *sbp)
(sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT);
}
+static inline bool xfs_sb_version_hasforcealign(struct xfs_sb *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
+ (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FORCEALIGN);
+}
+
static inline bool xfs_sb_version_needsrepair(struct xfs_sb *sbp)
{
return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
@@ -1170,15 +1178,18 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
#define XFS_DIFLAG2_REFLINK_BIT 1 /* file's blocks may be shared */
#define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */
#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_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_ANY \
(XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \
- XFS_DIFLAG2_BIGTIME)
+ XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_FORCEALIGN)
static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
{
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 7ecbfad..8a89685 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -551,6 +551,14 @@ xfs_dinode_verify(
!xfs_sb_version_hasbigtime(&mp->m_sb))
return __this_address;
+ if (flags2 & XFS_DIFLAG2_FORCEALIGN) {
+ fa = xfs_inode_validate_forcealign(mp, mode, flags,
+ be32_to_cpu(dip->di_extsize),
+ be32_to_cpu(dip->di_cowextsize));
+ if (fa)
+ return fa;
+ }
+
return NULL;
}
@@ -718,3 +726,35 @@ xfs_inode_validate_cowextsize(
return NULL;
}
+
+/* Validate the forcealign inode flag */
+xfs_failaddr_t
+xfs_inode_validate_forcealign(
+ struct xfs_mount *mp,
+ uint16_t mode,
+ uint16_t flags,
+ uint32_t extsize,
+ uint32_t cowextsize)
+{
+ /* superblock rocompat feature flag */
+ if (!xfs_sb_version_hasforcealign(&mp->m_sb))
+ return __this_address;
+
+ /* Only regular files and directories */
+ if (!S_ISDIR(mode) && !S_ISREG(mode))
+ return __this_address;
+
+ /* Doesn't apply to realtime files */
+ if (flags & XFS_DIFLAG_REALTIME)
+ return __this_address;
+
+ /* Requires a nonzero extent size hint */
+ if (extsize == 0)
+ return __this_address;
+
+ /* Requires no cow extent size hint */
+ if (cowextsize != 0)
+ return __this_address;
+
+ return NULL;
+}
diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h
index 7f865bb..56ed6d7 100644
--- a/libxfs/xfs_inode_buf.h
+++ b/libxfs/xfs_inode_buf.h
@@ -33,6 +33,9 @@ xfs_failaddr_t xfs_inode_validate_extsize(struct xfs_mount *mp,
xfs_failaddr_t xfs_inode_validate_cowextsize(struct xfs_mount *mp,
uint32_t cowextsize, uint16_t mode, uint16_t flags,
uint64_t flags2);
+xfs_failaddr_t xfs_inode_validate_forcealign(struct xfs_mount *mp,
+ uint16_t mode, uint16_t flags, uint32_t extsize,
+ uint32_t cowextsize);
static inline uint64_t xfs_inode_encode_bigtime(struct timespec64 tv)
{
--
2.33.0

View File

@ -0,0 +1,49 @@
From 066996554fe69ee6e8b2acfc59013414adc9669c Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Fri, 29 Sep 2023 09:53:37 +0000
Subject: [PATCH 02/11] xfs: allow files to require data mappings to be aligned
to extszhint
Conflict: xfs_bmapi_allocate is refactored in v6.4, so delete some code related
to alignment.
Add a new inode flag to require that all file data extent mappings must
be aligned (both the file offset range and the allocated space itself)
to the extent size hint. Having a separate COW extent size hint is no
longer allowed.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Co-developed-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
libxfs/xfs_bmap.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 16dbe71..303370e 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -3428,6 +3428,19 @@ xfs_bmap_compute_alignments(
align = xfs_get_cowextsz_hint(ap->ip);
else if (ap->datatype & XFS_ALLOC_USERDATA)
align = xfs_get_extsz_hint(ap->ip);
+
+ /*
+ * xfs_get_cowextsz_hint() returns extsz_hint for when forcealign is
+ * set as forcealign and cowextsz_hint are mutually exclusive
+ */
+ if (xfs_inode_forcealign(ap->ip) && align) {
+ args->alignment = align;
+ if (stripe_align % align)
+ stripe_align = align;
+ } else {
+ args->alignment = 1;
+ }
+
if (align) {
if (xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, align, 0,
ap->eof, 0, ap->conv, &ap->offset,
--
2.33.0

View File

@ -0,0 +1,45 @@
From a26e452c3e0cc84df8abd7cc8aabe4bc6d2f504d Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Fri, 29 Sep 2023 09:53:38 +0000
Subject: [PATCH 03/11] xfs_db: expose force_align feature and flags
Expose the superblock feature and inode flags.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
db/inode.c | 3 +++
db/sb.c | 2 ++
2 files changed, 5 insertions(+)
diff --git a/db/inode.c b/db/inode.c
index 3453c08..a859196 100644
--- a/db/inode.c
+++ b/db/inode.c
@@ -178,6 +178,9 @@ const field_t inode_v3_flds[] = {
{ "bigtime", FLDT_UINT1,
OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_BIGTIME_BIT - 1), C1,
0, TYP_NONE },
+ { "forcealign", FLDT_UINT1,
+ OI(COFF(flags2) + bitsz(uint64_t) - XFS_DIFLAG2_FORCEALIGN_BIT-1), C1,
+ 0, TYP_NONE },
{ NULL }
};
diff --git a/db/sb.c b/db/sb.c
index cec7dce..200deac 100644
--- a/db/sb.c
+++ b/db/sb.c
@@ -704,6 +704,8 @@ version_string(
strcat(s, ",BIGTIME");
if (xfs_sb_version_needsrepair(sbp))
strcat(s, ",NEEDSREPAIR");
+ if (xfs_sb_version_hasforcealign(sbp))
+ strcat(s, ",FORCEALIGN");
return s;
}
--
2.33.0

View File

@ -0,0 +1,68 @@
From 0825de7d2255ae25d7571a95244cc29095b044fe Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Fri, 29 Sep 2023 09:53:39 +0000
Subject: [PATCH 04/11] xfs_io: implement lsattr and chattr support for
forcealign
Make it so that we can adjust the forcealign flag at runtime.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Co-developed-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
io/attr.c | 5 ++++-
man/man2/ioctl_xfs_fsgetxattr.2 | 6 ++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/io/attr.c b/io/attr.c
index fd82a2e..248a9c2 100644
--- a/io/attr.c
+++ b/io/attr.c
@@ -38,9 +38,10 @@ static struct xflags {
{ FS_XFLAG_DAX, "x", "dax" },
{ FS_XFLAG_COWEXTSIZE, "C", "cowextsize" },
{ FS_XFLAG_HASATTR, "X", "has-xattr" },
+ { FS_XFLAG_FORCEALIGN, "F", "force-align" },
{ 0, NULL, NULL }
};
-#define CHATTR_XFLAG_LIST "r"/*p*/"iasAdtPneEfSxC"/*X*/
+#define CHATTR_XFLAG_LIST "r"/*p*/"iasAdtPneEfSxC"/*X*/"F"
static void
lsattr_help(void)
@@ -67,6 +68,7 @@ lsattr_help(void)
" x -- Use direct access (DAX) for data in this file\n"
" C -- for files with shared blocks, observe the inode CoW extent size value\n"
" X -- file has extended attributes (cannot be changed using chattr)\n"
+" F -- data extent mappings must be aligned to extent size hint\n"
"\n"
" Options:\n"
" -R -- recursively descend (useful when current file is a directory)\n"
@@ -104,6 +106,7 @@ chattr_help(void)
" +/-S -- set/clear the filestreams allocator flag\n"
" +/-x -- set/clear the direct access (DAX) flag\n"
" +/-C -- set/clear the CoW extent-size flag\n"
+" +/-F -- set/clear the forcealign flag\n"
" Note1: user must have certain capabilities to modify immutable/append-only.\n"
" Note2: immutable/append-only files cannot be deleted; removing these files\n"
" requires the immutable/append-only flag to be cleared first.\n"
diff --git a/man/man2/ioctl_xfs_fsgetxattr.2 b/man/man2/ioctl_xfs_fsgetxattr.2
index 2c626a7..d97fb1b 100644
--- a/man/man2/ioctl_xfs_fsgetxattr.2
+++ b/man/man2/ioctl_xfs_fsgetxattr.2
@@ -200,6 +200,12 @@ below).
If set on a directory, new files and subdirectories created in the directory
will have both the flag and the CoW extent size value set.
.TP
+.B XFS_XFLAG_FORCEALIGN
+Force Alignment bit - requires that all file data extents must be aligned
+to the extent size hint value.
+If set on a directory, new files and subdirectories created in the directory
+will have the flag set.
+.TP
.B XFS_XFLAG_HASATTR
The file has extended attributes associated with it.
--
2.33.0

View File

@ -0,0 +1,101 @@
From 2a14aafc618a9878d45240c4f0c1f0c7dc8f3d6b Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Fri, 29 Sep 2023 09:53:40 +0000
Subject: [PATCH 05/11] xfs_repair: check the force-align flag
Make sure the flag isn't set incorrectly.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
repair/dinode.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/repair/dinode.c b/repair/dinode.c
index f39ab2d..7747070 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -2229,6 +2229,69 @@ _("Bad extent size hint %u on inode %" PRIu64 ", "),
}
}
+static void
+validate_forcealign(
+ struct xfs_mount *mp,
+ struct xfs_dinode *dino,
+ xfs_ino_t lino,
+ int *dirty)
+{
+ uint16_t mode;
+ uint16_t flags;
+ uint64_t flags2;
+
+ mode = be16_to_cpu(dino->di_mode);
+ flags = be16_to_cpu(dino->di_flags);
+ flags2 = be64_to_cpu(dino->di_flags2);
+
+ if (!(flags2 & XFS_DIFLAG2_FORCEALIGN))
+ return;
+
+ if (!xfs_sb_version_hasforcealign(&mp->m_sb)) {
+ do_warn(
+ _("Filesystem does not support forcealign flag set on inode %" PRIu64 ", "),
+ lino);
+ goto zap;
+ }
+
+ if (!S_ISDIR(mode) && !S_ISREG(mode)) {
+ do_warn(
+ _("Cannot have forcealign inode flag set on non-dir non-regular file inode %" PRIu64 "\n"),
+ lino);
+ goto zap;
+ }
+
+ if (flags & XFS_DIFLAG_REALTIME) {
+ do_warn(
+ _("Cannot have forcealign inode flag set on realtime inode %" PRIu64 "\n"),
+ lino);
+ goto zap;
+ }
+
+ if (dino->di_extsize == 0) {
+ do_warn(
+ _("Cannot have forcealign inode flag set without an extent size hint on inode %" PRIu64 "\n"),
+ lino);
+ goto zap;
+ }
+
+ if (dino->di_cowextsize != 0) {
+ do_warn(
+ _("Cannot have forcealign inode flag set with nonzero CoW extent size hint on inode %" PRIu64 "\n"),
+ lino);
+ goto zap;
+ }
+
+ return;
+zap:
+ if (!no_modify) {
+ do_warn(_("clearing flag\n"));
+ dino->di_flags2 &= ~cpu_to_be64(XFS_DIFLAG2_FORCEALIGN);
+ *dirty = 1;
+ } else
+ do_warn(_("would clear flag\n"));
+}
+
/*
* returns 0 if the inode is ok, 1 if the inode is corrupt
* check_dups can be set to 1 *only* when called by the
@@ -2764,6 +2827,9 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "),
do_warn(_("would reset to zero\n"));
}
+ if (dino->di_version >= 3)
+ validate_forcealign(mp, dino, lino, dirty);
+
/* nsec fields cannot be larger than 1 billion */
check_nsec("atime", lino, dino, &dino->di_atime, dirty);
check_nsec("mtime", lino, dino, &dino->di_mtime, dirty);
--
2.33.0

View File

@ -0,0 +1,165 @@
From 53e0ead4c1a522f42486e47925b4c224945c6cda Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Fri, 29 Sep 2023 09:53:41 +0000
Subject: [PATCH 06/11] mkfs: add an extsize= option that allows units
Add a new mkfs option that allows the user to specify an extent size
hint with units. This removes the need to specify the option in
filesystem block size, which eases the computation requirements in
deployment scripts.
# mkfs.xfs -d extsize=2m /dev/sda
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
man/man8/mkfs.xfs.8 | 15 ++++++++++++++
mkfs/xfs_mkfs.c | 48 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8
index b2ffb3d..5cd69fa 100644
--- a/man/man8/mkfs.xfs.8
+++ b/man/man8/mkfs.xfs.8
@@ -479,6 +479,18 @@ will be assigned the project quota id provided in
Directories will pass on the project id to newly created regular files and
directories.
.TP
+.BI extsize= num
+All inodes created by
+.B mkfs.xfs
+will have this
+.I value
+extent size hint applied.
+Directories will pass on this hint to newly created regular files and
+directories.
+This option cannot be combined with the
+.B extszinherit
+option.
+.TP
.BI extszinherit= value
All inodes created by
.B mkfs.xfs
@@ -488,6 +500,9 @@ extent size hint applied.
The value must be provided in units of filesystem blocks.
Directories will pass on this hint to newly created regular files and
directories.
+This option cannot be combined with the
+.B extsize
+option.
.TP
.BI daxinherit= value
If
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 2eb3a0a..fb0c53f 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -66,6 +66,7 @@ enum {
D_NOALIGN,
D_RTINHERIT,
D_PROJINHERIT,
+ D_EXTSIZE,
D_EXTSZINHERIT,
D_COWEXTSIZE,
D_DAXINHERIT,
@@ -300,6 +301,7 @@ static struct opt_params dopts = {
[D_NOALIGN] = "noalign",
[D_RTINHERIT] = "rtinherit",
[D_PROJINHERIT] = "projinherit",
+ [D_EXTSIZE] = "extsize",
[D_EXTSZINHERIT] = "extszinherit",
[D_COWEXTSIZE] = "cowextsize",
[D_DAXINHERIT] = "daxinherit",
@@ -407,8 +409,17 @@ static struct opt_params dopts = {
.maxval = UINT_MAX,
.defaultval = SUBOPT_NEEDS_VAL,
},
+ { .index = D_EXTSIZE,
+ .conflicts = { { &dopts, D_EXTSZINHERIT },
+ { NULL, LAST_CONFLICT } },
+ .convert = true,
+ .minval = 0,
+ .maxval = XFS_AG_MAX_BYTES,
+ .defaultval = SUBOPT_NEEDS_VAL,
+ },
{ .index = D_EXTSZINHERIT,
- .conflicts = { { NULL, LAST_CONFLICT } },
+ .conflicts = { { &dopts, D_EXTSIZE },
+ { NULL, LAST_CONFLICT } },
.minval = 0,
.maxval = UINT_MAX,
.defaultval = SUBOPT_NEEDS_VAL,
@@ -835,6 +846,7 @@ struct cli_params {
char *lsu;
char *rtextsize;
char *rtsize;
+ char *extsize;
/* parameters where 0 is a valid CLI value */
int dsunit;
@@ -945,7 +957,7 @@ usage( void )
inobtcount=0|1,bigtime=0|1]\n\
/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\
(sunit=value,swidth=value|su=num,sw=num|noalign),\n\
- sectsize=num\n\
+ sectsize=num,extsize=num\n\
/* 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\
@@ -1553,6 +1565,9 @@ data_opts_parser(
cli->fsx.fsx_projid = getnum(value, opts, subopt);
cli->fsx.fsx_xflags |= FS_XFLAG_PROJINHERIT;
break;
+ case D_EXTSIZE:
+ cli->extsize = getstr(value, opts, subopt);
+ break;
case D_EXTSZINHERIT:
cli->fsx.fsx_extsize = getnum(value, opts, subopt);
if (cli->fsx.fsx_extsize)
@@ -2002,6 +2017,33 @@ _("Minimum block size for CRC enabled filesystems is %d bytes.\n"),
}
+/*
+ * Convert the -d extsize= option to a number, then set the extent size hint
+ * to that number.
+ */
+static void
+set_extsize(
+ struct cli_params *cli,
+ char *extsize,
+ struct opt_params *opts,
+ int subopt)
+{
+ uint64_t extsz_bytes;
+ if (!extsize)
+ return;
+
+ extsz_bytes = getnum(extsize, opts, subopt);
+ if (extsz_bytes % blocksize)
+ illegal_option(extsize, opts, subopt,
+ _("Value must be a multiple of block size."));
+
+ cli->fsx.fsx_extsize = extsz_bytes / blocksize;
+ if (cli->fsx.fsx_extsize)
+ cli->fsx.fsx_xflags |= FS_XFLAG_EXTSZINHERIT;
+ else
+ cli->fsx.fsx_xflags &= ~FS_XFLAG_EXTSZINHERIT;
+}
+
/*
* Grab log sector size and validate.
*
@@ -4081,6 +4123,8 @@ main(
blocksize = cfg.blocksize;
sectorsize = cfg.sectorsize;
+ set_extsize(&cli, cli.extsize, &dopts, D_EXTSIZE);
+
validate_log_sectorsize(&cfg, &cli, &dft);
validate_sb_features(&cfg, &cli);
--
2.33.0

View File

@ -0,0 +1,314 @@
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

View File

@ -0,0 +1,193 @@
From c85d383b0bb1d86c676ccf817dd22ad43b589b61 Mon Sep 17 00:00:00 2001
From: John Garry <john.g.garry@oracle.com>
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 <john.g.garry@oracle.com>
---
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 <linux/fsmap.h>
#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

View File

@ -0,0 +1,105 @@
From eb775dfcd8c48d4a60f3989f5b5707c96a9612f4 Mon Sep 17 00:00:00 2001
From: John Garry <john.g.garry@oracle.com>
Date: Mon, 4 Mar 2024 10:27:27 +0000
Subject: [PATCH 10/11] xfs_io: Support statx for atomic writes
This should be done properly by installing the kernel headers with
atomic write statx support.
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
io/stat.c | 3 +++
io/statx.h | 20 +++++++++++++++++++-
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/io/stat.c b/io/stat.c
index b57f9ee..d7f4047 100644
--- a/io/stat.c
+++ b/io/stat.c
@@ -434,6 +434,9 @@ statx_f(
printf(_("stat.btime = %s"),
ctime((time_t *)&stx.stx_btime.tv_sec));
}
+ printf(_("stat.stx_atomic_write_unit_min = %lld\n"), (long long)stx.stx_atomic_write_unit_min);
+ printf(_("stat.stx_atomic_write_unit_max = %lld\n"), (long long)stx.stx_atomic_write_unit_max);
+ printf(_("stat.stx_atomic_write_segments_max = %lld\n"), (long long)stx.stx_atomic_write_segments_max);
if (file->flags & IO_FOREIGN)
return 0;
diff --git a/io/statx.h b/io/statx.h
index c6625ac..80745e8 100644
--- a/io/statx.h
+++ b/io/statx.h
@@ -34,6 +34,7 @@
#endif
+#undef STATX_TYPE
#ifndef STATX_TYPE
/* Pick up kernel definitions if glibc didn't already provide them */
#include <linux/stat.h>
@@ -56,6 +57,9 @@
*
* __reserved is held in case we need a yet finer resolution.
*/
+#define statx_timestamp _statx_timestamp
+#undef _statx_timestamp
+
struct statx_timestamp {
__s64 tv_sec;
__s32 tv_nsec;
@@ -99,6 +103,8 @@ struct statx_timestamp {
* will have values installed for compatibility purposes so that stat() and
* co. can be emulated in userspace.
*/
+#define statx _statx
+#undef _statx
struct statx {
/* 0x00 */
__u32 stx_mask; /* What results were written [uncond] */
@@ -126,7 +132,16 @@ struct statx {
__u32 stx_dev_major; /* ID of device containing file [uncond] */
__u32 stx_dev_minor;
/* 0x90 */
- __u64 __spare2[14]; /* Spare space for future expansion */
+ __u64 stx_mnt_id;
+ __u32 stx_dio_mem_align; /* Memory buffer alignment for direct I/O */
+ __u32 stx_dio_offset_align; /* File offset alignment for direct I/O */
+ /* 0xa0 */
+ __u32 stx_atomic_write_unit_min; /* Min atomic write unit in bytes */
+ __u32 stx_atomic_write_unit_max; /* Max atomic write unit in bytes */
+ __u32 stx_atomic_write_segments_max; /* Max atomic write segment count */
+ __u32 __spare1;
+ /* 0xb0 */
+ __u64 __spare3[10]; /* Spare space for future expansion */
/* 0x100 */
};
@@ -138,6 +153,7 @@ struct statx {
* These bits should be set in the mask argument of statx() to request
* particular items when calling statx().
*/
+#undef STATX_ALL
#define STATX_TYPE 0x00000001U /* Want/got stx_mode & S_IFMT */
#define STATX_MODE 0x00000002U /* Want/got stx_mode & ~S_IFMT */
#define STATX_NLINK 0x00000004U /* Want/got stx_nlink */
@@ -151,6 +167,7 @@ struct statx {
#define STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */
#define STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */
#define STATX_BTIME 0x00000800U /* Want/got stx_btime */
+#define STATX_WRITE_ATOMIC 0x00008000U /* Want/got atomic_write_* fields */
#define STATX_ALL 0x00000fffU /* All currently supported flags */
#define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */
@@ -172,6 +189,7 @@ struct statx {
#define STATX_ATTR_ENCRYPTED 0x00000800 /* [I] File requires key to decrypt in fs */
#define STATX_ATTR_AUTOMOUNT 0x00001000 /* Dir: Automount trigger */
+#define STATX_ATTR_WRITE_ATOMIC 0x00400000 /* File supports atomic write operations */
#endif /* STATX_TYPE */
#endif /* XFS_IO_STATX_H */
--
2.33.0

View File

@ -0,0 +1,35 @@
From d95dc0f4b90de16168c533e495c5ee1e012e41fd Mon Sep 17 00:00:00 2001
From: John Garry <john.g.garry@oracle.com>
Date: Thu, 21 Mar 2024 12:20:37 +0000
Subject: [PATCH 11/11] mkfs: Ensure extsize aligned to stripe unit for
forcealign
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
mkfs/xfs_mkfs.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c
index 5169255..cf0852f 100644
--- a/mkfs/xfs_mkfs.c
+++ b/mkfs/xfs_mkfs.c
@@ -2754,6 +2754,16 @@ _("%s: Stripe unit(%d) or stripe width(%d) is not a multiple of the block size(%
cfg->dsunit = DTOBT(dsunit, cfg->blocklog);
cfg->dswidth = DTOBT(dswidth, cfg->blocklog);
+ if (cli->fsx.fsx_xflags & FS_XFLAG_FORCEALIGN) {
+ if ((cfg->dsunit % cli->fsx.fsx_extsize) ||
+ (cfg->dswidth % cli->fsx.fsx_extsize)) {
+ fprintf(stderr,
+ _("Stripe unit(%d) or stripe width(%d) is not a multiple of the extsize (%d) for forcealign\n"),
+ cfg->dsunit, cfg->dswidth, cli->fsx.fsx_extsize);
+ usage();
+ }
+ }
+
check_lsunit:
/* log sunit options */
if (cli_opt_set(&lopts, L_SUNIT))
--
2.33.0

View File

@ -0,0 +1,51 @@
From 1e02682bf6204656f37e7c0d30aef29c6a246cb2 Mon Sep 17 00:00:00 2001
From: John Garry <john.g.garry@oracle.com>
Date: Fri, 1 Mar 2024 17:15:22 +0000
Subject: [PATCH 09/11] xfs_io: Implement lsattr and chattr support for atomic
writes
Use something like the following:
xfs_io -c "chattr +W" mnt/file
forcealign must be aliged for the file.
Signed-off-by: John Garry <john.g.garry@oracle.com>
---
io/attr.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/io/attr.c b/io/attr.c
index 248a9c2..bc27a1a 100644
--- a/io/attr.c
+++ b/io/attr.c
@@ -39,9 +39,10 @@ static struct xflags {
{ FS_XFLAG_COWEXTSIZE, "C", "cowextsize" },
{ FS_XFLAG_HASATTR, "X", "has-xattr" },
{ FS_XFLAG_FORCEALIGN, "F", "force-align" },
+ { FS_XFLAG_ATOMICWRITES, "W", "atomic-writes" },
{ 0, NULL, NULL }
};
-#define CHATTR_XFLAG_LIST "r"/*p*/"iasAdtPneEfSxC"/*X*/"F"
+#define CHATTR_XFLAG_LIST "r"/*p*/"iasAdtPneEfSxC"/*X*/"FW"
static void
lsattr_help(void)
@@ -69,6 +70,7 @@ lsattr_help(void)
" C -- for files with shared blocks, observe the inode CoW extent size value\n"
" X -- file has extended attributes (cannot be changed using chattr)\n"
" F -- data extent mappings must be aligned to extent size hint\n"
+" W -- atomic writes enabled for a file\n"
"\n"
" Options:\n"
" -R -- recursively descend (useful when current file is a directory)\n"
@@ -107,6 +109,7 @@ chattr_help(void)
" +/-x -- set/clear the direct access (DAX) flag\n"
" +/-C -- set/clear the CoW extent-size flag\n"
" +/-F -- set/clear the forcealign flag\n"
+" +/-W -- set/clear the atomic writes flag\n"
" Note1: user must have certain capabilities to modify immutable/append-only.\n"
" Note2: immutable/append-only files cannot be deleted; removing these files\n"
" requires the immutable/append-only flag to be cleared first.\n"
--
2.33.0

View File

@ -1,6 +1,6 @@
Name: xfsprogs Name: xfsprogs
Version: 5.14.1 Version: 5.14.1
Release: 15 Release: 16
Summary: Administration and debugging tools for the XFS file system Summary: Administration and debugging tools for the XFS file system
License: GPL+ and LGPLv2+ License: GPL+ and LGPLv2+
URL: https://xfs.wiki.kernel.org URL: https://xfs.wiki.kernel.org
@ -65,7 +65,17 @@ Patch43: 0043-xfs_repair-retain-superblock-buffer-to-avoid-write-h.patch
Patch44: 0044-fsck.xfs-mount-umount-xfs-fs-to-replay-log-before-ru.patch Patch44: 0044-fsck.xfs-mount-umount-xfs-fs-to-replay-log-before-ru.patch
Patch45: 0045-xfs_db-fix-dir3-block-magic-check.patch Patch45: 0045-xfs_db-fix-dir3-block-magic-check.patch
Patch46: 0046-xfs_repair-fix-incorrect-dabtree-hashval-comparison.patch Patch46: 0046-xfs_repair-fix-incorrect-dabtree-hashval-comparison.patch
Patch47: 0047-xfs-create-a-new-inode-flag-to-require-extsize-align.patch
Patch48: 0048-xfs-allow-files-to-require-data-mappings-to-be-align.patch
Patch49: 0049-xfs_db-expose-force_align-feature-and-flags.patch
Patch50: 0050-xfs_io-implement-lsattr-and-chattr-support-for-force.patch
Patch51: 0051-xfs_repair-check-the-force-align-flag.patch
Patch52: 0052-mkfs-add-an-extsize-option-that-allows-units.patch
Patch53: 0053-mkfs-enable-the-new-force-align-feature.patch
Patch54: 0054-mkfs-Add-atomic-writes-suppport.patch
Patch55: 0055-xfs_io-Support-statx-for-atomic-writes.patch
Patch56: 0056-mkfs-Ensure-extsize-aligned-to-stripe-unit-for-force.patch
Patch57: 0057-xfs_io-Implement-lsattr-and-chattr-support-for-atomi.patch
%description %description
xfsprogs are the userspace utilities that manage XFS filesystems. xfsprogs are the userspace utilities that manage XFS filesystems.
@ -149,6 +159,10 @@ rm -rf %{buildroot}%{_datadir}/doc/xfsprogs/
%changelog %changelog
* Mon May 20 2024 zhangjian <zhangjian496@huawei.com> - 5.14.1-16
- support atomic write
* Wed Dec 27 2023 wuguanghao <wuguanghao3@huawei.com> - 5.14.1-15 * Wed Dec 27 2023 wuguanghao <wuguanghao3@huawei.com> - 5.14.1-15
- backport patches from community - backport patches from community