diff --git a/0047-xfs-create-a-new-inode-flag-to-require-extsize-align.patch b/0047-xfs-create-a-new-inode-flag-to-require-extsize-align.patch new file mode 100644 index 0000000000000000000000000000000000000000..488858b263f2c9561f77827d5b0fd23fe5d13aa7 --- /dev/null +++ b/0047-xfs-create-a-new-inode-flag-to-require-extsize-align.patch @@ -0,0 +1,198 @@ +From 983997ce4b8de736c5c10c33c6cf4e40076dcbdf Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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" +Co-developed-by: John Garry +Signed-off-by: John Garry + +--- + 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 + #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 diff --git a/0048-xfs-allow-files-to-require-data-mappings-to-be-align.patch b/0048-xfs-allow-files-to-require-data-mappings-to-be-align.patch new file mode 100644 index 0000000000000000000000000000000000000000..30bf01490db306b6e69f494aaccb7f1b8451fee4 --- /dev/null +++ b/0048-xfs-allow-files-to-require-data-mappings-to-be-align.patch @@ -0,0 +1,49 @@ +From 066996554fe69ee6e8b2acfc59013414adc9669c Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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" +Co-developed-by: John Garry +Signed-off-by: John Garry + +--- + 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 + diff --git a/0049-xfs_db-expose-force_align-feature-and-flags.patch b/0049-xfs_db-expose-force_align-feature-and-flags.patch new file mode 100644 index 0000000000000000000000000000000000000000..cd16a7ef0fa4f81e27e313420b19b3c0142edf60 --- /dev/null +++ b/0049-xfs_db-expose-force_align-feature-and-flags.patch @@ -0,0 +1,45 @@ +From a26e452c3e0cc84df8abd7cc8aabe4bc6d2f504d Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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" +Signed-off-by: John Garry + +--- + 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 + diff --git a/0050-xfs_io-implement-lsattr-and-chattr-support-for-force.patch b/0050-xfs_io-implement-lsattr-and-chattr-support-for-force.patch new file mode 100644 index 0000000000000000000000000000000000000000..ba1603e7fd42a36406689cb6ec7c713a3df086ad --- /dev/null +++ b/0050-xfs_io-implement-lsattr-and-chattr-support-for-force.patch @@ -0,0 +1,68 @@ +From 0825de7d2255ae25d7571a95244cc29095b044fe Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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" +Co-developed-by: John Garry +Signed-off-by: John Garry +--- + 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 + diff --git a/0051-xfs_repair-check-the-force-align-flag.patch b/0051-xfs_repair-check-the-force-align-flag.patch new file mode 100644 index 0000000000000000000000000000000000000000..2ec952f2e11b0ddbbb72533799120fcf3082a233 --- /dev/null +++ b/0051-xfs_repair-check-the-force-align-flag.patch @@ -0,0 +1,101 @@ +From 2a14aafc618a9878d45240c4f0c1f0c7dc8f3d6b Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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" +Signed-off-by: John Garry + +--- + 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 + diff --git a/0052-mkfs-add-an-extsize-option-that-allows-units.patch b/0052-mkfs-add-an-extsize-option-that-allows-units.patch new file mode 100644 index 0000000000000000000000000000000000000000..e6d5fb575fbfc419d777ad4835dbc7e2f83f18f1 --- /dev/null +++ b/0052-mkfs-add-an-extsize-option-that-allows-units.patch @@ -0,0 +1,165 @@ +From 53e0ead4c1a522f42486e47925b4c224945c6cda Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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" +Signed-off-by: John Garry + +--- + 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 + diff --git a/0053-mkfs-enable-the-new-force-align-feature.patch b/0053-mkfs-enable-the-new-force-align-feature.patch new file mode 100644 index 0000000000000000000000000000000000000000..d99cc12f8fa543891099d62c040e0955c0084420 --- /dev/null +++ b/0053-mkfs-enable-the-new-force-align-feature.patch @@ -0,0 +1,314 @@ +From 2c0500e6036dc996ea9553c9d56b26f54d815e45 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +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" +Signed-off-by: John Garry + +--- + 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 + diff --git a/0054-mkfs-Add-atomic-writes-suppport.patch b/0054-mkfs-Add-atomic-writes-suppport.patch new file mode 100644 index 0000000000000000000000000000000000000000..a6c80a0dca43a82c1f8108d4e2d2d2c0134cbce8 --- /dev/null +++ b/0054-mkfs-Add-atomic-writes-suppport.patch @@ -0,0 +1,193 @@ +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 + diff --git a/0055-xfs_io-Support-statx-for-atomic-writes.patch b/0055-xfs_io-Support-statx-for-atomic-writes.patch new file mode 100644 index 0000000000000000000000000000000000000000..c789294b850fb977f09098ec65ee9c1cdb0b90f9 --- /dev/null +++ b/0055-xfs_io-Support-statx-for-atomic-writes.patch @@ -0,0 +1,105 @@ +From eb775dfcd8c48d4a60f3989f5b5707c96a9612f4 Mon Sep 17 00:00:00 2001 +From: John Garry +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 + +--- + 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 +@@ -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 + diff --git a/0056-mkfs-Ensure-extsize-aligned-to-stripe-unit-for-force.patch b/0056-mkfs-Ensure-extsize-aligned-to-stripe-unit-for-force.patch new file mode 100644 index 0000000000000000000000000000000000000000..e4e562394d38430d156b6f602fc6bb40354e1100 --- /dev/null +++ b/0056-mkfs-Ensure-extsize-aligned-to-stripe-unit-for-force.patch @@ -0,0 +1,35 @@ +From d95dc0f4b90de16168c533e495c5ee1e012e41fd Mon Sep 17 00:00:00 2001 +From: John Garry +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 +--- + 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 + diff --git a/0057-xfs_io-Implement-lsattr-and-chattr-support-for-atomi.patch b/0057-xfs_io-Implement-lsattr-and-chattr-support-for-atomi.patch new file mode 100644 index 0000000000000000000000000000000000000000..0f8bcf7f21d2cc13381f90bc8d98d25e0279b5ee --- /dev/null +++ b/0057-xfs_io-Implement-lsattr-and-chattr-support-for-atomi.patch @@ -0,0 +1,51 @@ +From 1e02682bf6204656f37e7c0d30aef29c6a246cb2 Mon Sep 17 00:00:00 2001 +From: John Garry +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 +--- + 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 + diff --git a/xfsprogs.spec b/xfsprogs.spec index aeba965725587a608faab2af8da6e86a3e1ce130..6d6cc170ca8be8e9ae0aa67387041134164c366d 100644 --- a/xfsprogs.spec +++ b/xfsprogs.spec @@ -1,6 +1,6 @@ Name: xfsprogs Version: 5.14.1 -Release: 15 +Release: 16 Summary: Administration and debugging tools for the XFS file system License: GPL+ and LGPLv2+ 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 Patch45: 0045-xfs_db-fix-dir3-block-magic-check.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 xfsprogs are the userspace utilities that manage XFS filesystems. @@ -149,6 +159,10 @@ rm -rf %{buildroot}%{_datadir}/doc/xfsprogs/ %changelog + +* Mon May 20 2024 zhangjian - 5.14.1-16 +- support atomic write + * Wed Dec 27 2023 wuguanghao - 5.14.1-15 - backport patches from community