* [PATCH 00/28] xfsprogs: libxfs sync for v7.3
@ 2026-10-29 12:05 Andrey Albershteyn
2026-10-29 12:05 ` [PATCH 01/28] xfs: add xfs_metadir_create_file helper Andrey Albershteyn
` (28 more replies)
0 siblings, 29 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:05 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling, Andrey Albershteyn
Hi folks,
Resending Darrick's libxfs sync for v7.2..v7.3 with comments from hch
addressed.
(not sure if Darrick planned to resend it, I've just pulled it from his
branch)
Christoph Hellwig (2):
xfs: remove spurious XBF_DONE clearing on readahead validation failure
xfs: hide b_flags manipulation from code outside of xfs_buf.c
Cihan Karadag (1):
xfs: use kmalloc_objs() instead of kmalloc() in xfs_da_grow_inode_int
Darrick J. Wong (8):
xfs: fix the rtrmap and rtrefcount _maxlevels_ondisk functions
xfs: fix xfs_rtrmapbt_mem_cursor for non-rmap filesystems
xfs: preserve owner on in-memory btree creation
xfs: don't leak new_bp if xfs_btree_bload_drop_buf fails
xfs: fix under-reservation of blocks when repairing sf directories
xfs: don't let hidden_space go negative in xfs_metafile_resv_init
xfs: fix wild memcpy access when formatting ondisk rtrefcount btree
roots
xfs: fix exchange-range-to-eof file size exchange
Hemanth Selam (1):
xfs: fix typos and repeated words in comments
Hongling Zeng (1):
xfs: validate attr entry pointer before field access
Javier Tia (6):
xfs: initialise error in xfs_defer_finish_one()
xfs: give the deferred barrier op type a name
xfs: report the error that made deferred work shut down the fs
xfs: correct the parent pointer space reservation comment
xfs: initialise args->total for parent pointer updates
xfs: assert the reservation covers each da fork growth
Jiangshan Yi (1):
xfs: remove duplicate INO1_WRITTEN check
Johannes Thumshirn (4):
xfs: add xfs_metadir_create_file helper
xfs: create quota metadir inodes using xfs_metadir_create_file
xfs: create rtgroup metadir inodes using xfs_metadir_create_file
xfs: mark internal metadir file creation helpers static
Kees Cook (1):
treewide: refresh kmalloc_obj() conversions
Lin Jiapeng (1):
xfs: fix exchange-range reflink flag clearing issue with INO1_WRITTEN
Norbert Szetei (1):
xfs: stop exchanging reflink flags when exchanging mappings
Yun Zhou (1):
xfs: don't hold buffer locks across sync transaction commit in
xfs_sync_sb_buf
include/kmem.h | 14 ++++++
libxfs/stubs/xfs_mount.h | 4 ++
libxfs/xfs_ag.h | 2 +-
libxfs/xfs_alloc.c | 4 +-
libxfs/xfs_attr_leaf.c | 16 +++++-
libxfs/xfs_btree_mem.c | 2 +
libxfs/xfs_btree_staging.c | 11 ++--
libxfs/xfs_da_btree.c | 10 ++--
libxfs/xfs_da_btree.h | 2 +
libxfs/xfs_defer.c | 18 ++++++-
libxfs/xfs_dquot_buf.c | 47 ++++++-----------
libxfs/xfs_errortag.h | 2 +-
libxfs/xfs_exchmaps.c | 95 ++++++-----------------------------
libxfs/xfs_format.h | 2 +-
libxfs/xfs_ialloc.c | 2 +-
libxfs/xfs_inode_buf.c | 17 ++++---
libxfs/xfs_log_format.h | 4 +-
libxfs/xfs_metadir.c | 84 ++++++++++++++++++-------------
libxfs/xfs_metadir.h | 8 +--
libxfs/xfs_metafile.c | 8 +--
libxfs/xfs_parent.c | 12 ++++-
libxfs/xfs_platform.h | 5 ++
libxfs/xfs_rtgroup.c | 58 ++++++++++-----------
libxfs/xfs_rtgroup.h | 6 ++-
libxfs/xfs_rtrefcount_btree.c | 11 ++--
libxfs/xfs_rtrmap_btree.c | 6 ++-
libxfs/xfs_sb.c | 37 +++++++-------
libxfs/xfs_trans_space.c | 19 ++++++-
28 files changed, 259 insertions(+), 247 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 01/28] xfs: add xfs_metadir_create_file helper
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
@ 2026-10-29 12:05 ` Andrey Albershteyn
2026-10-29 12:05 ` [PATCH 02/28] xfs: create quota metadir inodes using xfs_metadir_create_file Andrey Albershteyn
` (27 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:05 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Source kernel commit: daf43402da0d3a66eda26fefe3473799165bd7b2
Factor the metadata inode create/commit/cleanup lifecycle out of
xfs_metadir_mkdir into a reusable helper that takes an optional callback
to initialize the new inode, and convert xfs_metadir_mkdir to it.
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_metadir.c | 78 ++++++++++++++++++++++++++------------------
libxfs/xfs_metadir.h | 6 ++++
2 files changed, 53 insertions(+), 31 deletions(-)
diff --git a/libxfs/xfs_metadir.c b/libxfs/xfs_metadir.c
index 74c4596ee4cf..0d6a153bc9e9 100644
--- a/libxfs/xfs_metadir.c
+++ b/libxfs/xfs_metadir.c
@@ -438,6 +438,52 @@ xfs_metadir_cancel(
xfs_metadir_teardown(upd, error);
}
+int
+xfs_metadir_create_file(
+ struct xfs_metadir_update *upd,
+ umode_t mode,
+ xfs_metadir_createfn create,
+ void *priv,
+ struct xfs_inode **ipp)
+{
+ int error;
+
+ if (xfs_is_shutdown(upd->dp->i_mount))
+ return -EIO;
+
+ error = xfs_metadir_start_create(upd);
+ if (error)
+ return error;
+
+ error = xfs_metadir_create(upd, mode);
+ if (error)
+ goto out_cancel;
+
+ if (create) {
+ error = create(upd, priv);
+ if (error)
+ goto out_cancel;
+ }
+
+ error = xfs_metadir_commit(upd);
+ if (error)
+ goto out_irele;
+
+ xfs_finish_inode_setup(upd->ip);
+ *ipp = upd->ip;
+ return 0;
+
+out_cancel:
+ xfs_metadir_cancel(upd, error);
+out_irele:
+ /* Have to finish setting up the inode to ensure it's deleted. */
+ if (upd->ip) {
+ xfs_finish_inode_setup(upd->ip);
+ xfs_irele(upd->ip);
+ }
+ return error;
+}
+
/* Create a metadata for the last component of the path. */
int
xfs_metadir_mkdir(
@@ -450,36 +496,6 @@ xfs_metadir_mkdir(
.path = path,
.metafile_type = XFS_METAFILE_DIR,
};
- int error;
- if (xfs_is_shutdown(dp->i_mount))
- return -EIO;
-
- /* Allocate a transaction to create the last directory. */
- error = xfs_metadir_start_create(&upd);
- if (error)
- return error;
-
- /* Create the subdirectory and take our reference. */
- error = xfs_metadir_create(&upd, S_IFDIR);
- if (error)
- goto out_cancel;
-
- error = xfs_metadir_commit(&upd);
- if (error)
- goto out_irele;
-
- xfs_finish_inode_setup(upd.ip);
- *ipp = upd.ip;
- return 0;
-
-out_cancel:
- xfs_metadir_cancel(&upd, error);
-out_irele:
- /* Have to finish setting up the inode to ensure it's deleted. */
- if (upd.ip) {
- xfs_finish_inode_setup(upd.ip);
- xfs_irele(upd.ip);
- }
- return error;
+ return xfs_metadir_create_file(&upd, S_IFDIR, NULL, NULL, ipp);
}
diff --git a/libxfs/xfs_metadir.h b/libxfs/xfs_metadir.h
index bfecac7d3d14..a795a2d0e3fe 100644
--- a/libxfs/xfs_metadir.h
+++ b/libxfs/xfs_metadir.h
@@ -35,6 +35,12 @@ int xfs_metadir_load(struct xfs_trans *tp, struct xfs_inode *dp,
int xfs_metadir_start_create(struct xfs_metadir_update *upd);
int xfs_metadir_create(struct xfs_metadir_update *upd, umode_t mode);
+typedef int (*xfs_metadir_createfn)(struct xfs_metadir_update *upd, void *priv);
+
+int xfs_metadir_create_file(struct xfs_metadir_update *upd, umode_t mode,
+ xfs_metadir_createfn create, void *priv,
+ struct xfs_inode **ipp);
+
int xfs_metadir_start_link(struct xfs_metadir_update *upd);
int xfs_metadir_link(struct xfs_metadir_update *upd);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 02/28] xfs: create quota metadir inodes using xfs_metadir_create_file
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
2026-10-29 12:05 ` [PATCH 01/28] xfs: add xfs_metadir_create_file helper Andrey Albershteyn
@ 2026-10-29 12:05 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 03/28] xfs: create rtgroup " Andrey Albershteyn
` (26 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:05 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Source kernel commit: e6ecb1a98d14b1e9ef0cd8f3340d30b5f491d2bc
Now that we have xfs_metadir_create_file() use it in
xfs_dqinode_metadir_create().
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_dquot_buf.c | 39 +++++++++++----------------------------
1 file changed, 11 insertions(+), 28 deletions(-)
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
index 0e59106303c4..21e74d6d17d9 100644
--- a/libxfs/xfs_dquot_buf.c
+++ b/libxfs/xfs_dquot_buf.c
@@ -415,6 +415,15 @@ xfs_dqinode_load(
return 0;
}
+static int
+xfs_dqinode_init(
+ struct xfs_metadir_update *upd,
+ void *priv)
+{
+ xfs_trans_log_inode(upd->tp, upd->ip, XFS_ILOG_CORE);
+ return 0;
+}
+
/* Create a metadata directory quota inode. */
int
xfs_dqinode_metadir_create(
@@ -427,35 +436,9 @@ xfs_dqinode_metadir_create(
.metafile_type = xfs_dqinode_metafile_type(type),
.path = xfs_dqinode_path(type),
};
- int error;
- error = xfs_metadir_start_create(&upd);
- if (error)
- return error;
-
- error = xfs_metadir_create(&upd, S_IFREG);
- if (error)
- goto out_cancel;
-
- xfs_trans_log_inode(upd.tp, upd.ip, XFS_ILOG_CORE);
-
- error = xfs_metadir_commit(&upd);
- if (error)
- goto out_irele;
-
- xfs_finish_inode_setup(upd.ip);
- *ipp = upd.ip;
- return 0;
-
-out_cancel:
- xfs_metadir_cancel(&upd, error);
-out_irele:
- /* Have to finish setting up the inode to ensure it's deleted. */
- if (upd.ip) {
- xfs_finish_inode_setup(upd.ip);
- xfs_irele(upd.ip);
- }
- return error;
+ return xfs_metadir_create_file(&upd, S_IFREG, xfs_dqinode_init, NULL,
+ ipp);
}
#ifndef __KERNEL__
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 03/28] xfs: create rtgroup metadir inodes using xfs_metadir_create_file
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
2026-10-29 12:05 ` [PATCH 01/28] xfs: add xfs_metadir_create_file helper Andrey Albershteyn
2026-10-29 12:05 ` [PATCH 02/28] xfs: create quota metadir inodes using xfs_metadir_create_file Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 04/28] xfs: mark internal metadir file creation helpers static Andrey Albershteyn
` (25 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Source kernel commit: de64b150a70cbf4e9499921d6cb7dc52fbeb55f7
Now that we have xfs_metadir_create_file() use it in
xfs_rtginode_create().
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_rtgroup.c | 58 ++++++++++++++++++++------------------------
1 file changed, 26 insertions(+), 32 deletions(-)
diff --git a/libxfs/xfs_rtgroup.c b/libxfs/xfs_rtgroup.c
index 2bbe651b773a..c6981f566860 100644
--- a/libxfs/xfs_rtgroup.c
+++ b/libxfs/xfs_rtgroup.c
@@ -516,6 +516,25 @@ xfs_rtginode_irele(
*ipp = NULL;
}
+struct xfs_rtginode_create {
+ struct xfs_rtgroup *rtg;
+ enum xfs_rtg_inodes type;
+ bool init;
+};
+
+static int
+xfs_rtginode_init(
+ struct xfs_metadir_update *upd,
+ void *priv)
+{
+ struct xfs_rtginode_create *rc = priv;
+ const struct xfs_rtginode_ops *ops = &xfs_rtginode_ops[rc->type];
+
+ xfs_rtginode_lockdep_setup(upd->ip, rtg_rgno(rc->rtg), rc->type);
+ upd->ip->i_projid = rtg_rgno(rc->rtg);
+ return ops->create(rc->rtg, upd->ip, upd->tp, rc->init);
+}
+
/* Add a metadata inode for a realtime rmap btree. */
int
xfs_rtginode_create(
@@ -525,6 +544,11 @@ xfs_rtginode_create(
{
const struct xfs_rtginode_ops *ops = &xfs_rtginode_ops[type];
struct xfs_mount *mp = rtg_mount(rtg);
+ struct xfs_rtginode_create rc = {
+ .rtg = rtg,
+ .type = type,
+ .init = init,
+ };
struct xfs_metadir_update upd = {
.dp = mp->m_rtdirip,
.metafile_type = ops->metafile_type,
@@ -543,38 +567,8 @@ xfs_rtginode_create(
if (!upd.path)
return -ENOMEM;
- error = xfs_metadir_start_create(&upd);
- if (error)
- goto out_path;
-
- error = xfs_metadir_create(&upd, S_IFREG);
- if (error)
- goto out_cancel;
-
- xfs_rtginode_lockdep_setup(upd.ip, rtg_rgno(rtg), type);
-
- upd.ip->i_projid = rtg_rgno(rtg);
- error = ops->create(rtg, upd.ip, upd.tp, init);
- if (error)
- goto out_cancel;
-
- error = xfs_metadir_commit(&upd);
- if (error)
- goto out_path;
-
- kfree(upd.path);
- xfs_finish_inode_setup(upd.ip);
- rtg->rtg_inodes[type] = upd.ip;
- return 0;
-
-out_cancel:
- xfs_metadir_cancel(&upd, error);
- /* Have to finish setting up the inode to ensure it's deleted. */
- if (upd.ip) {
- xfs_finish_inode_setup(upd.ip);
- xfs_irele(upd.ip);
- }
-out_path:
+ error = xfs_metadir_create_file(&upd, S_IFREG, xfs_rtginode_init, &rc,
+ &rtg->rtg_inodes[type]);
kfree(upd.path);
return error;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 04/28] xfs: mark internal metadir file creation helpers static
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (2 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 03/28] xfs: create rtgroup " Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 05/28] xfs: use kmalloc_objs() instead of kmalloc() in xfs_da_grow_inode_int Andrey Albershteyn
` (24 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Source kernel commit: c6c54d05b129c4e29f2fdc6d356b5be10765231d
Now that there is xfs_metadir_create_file() mark
xfs_metadir_start_create(), xfs_metadir_create() and xfs_metadir_cancel()
as static and remove them from xfs_metadir.h.
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_metadir.c | 6 +++---
libxfs/xfs_metadir.h | 4 ----
2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/libxfs/xfs_metadir.c b/libxfs/xfs_metadir.c
index 0d6a153bc9e9..7c6b086b73db 100644
--- a/libxfs/xfs_metadir.c
+++ b/libxfs/xfs_metadir.c
@@ -182,7 +182,7 @@ xfs_metadir_teardown(
* Begin the process of creating a metadata file by allocating transactions
* and taking whatever resources we're going to need.
*/
-int
+static int
xfs_metadir_start_create(
struct xfs_metadir_update *upd)
{
@@ -236,7 +236,7 @@ out_teardown:
* a negative error code. If an inode is passed back, the caller must finish
* setting up the inode before releasing it.
*/
-int
+static int
xfs_metadir_create(
struct xfs_metadir_update *upd,
umode_t mode)
@@ -425,7 +425,7 @@ xfs_metadir_commit(
}
/* Cancel a metadir update and unlock/drop all resources. */
-void
+static void
xfs_metadir_cancel(
struct xfs_metadir_update *upd,
int error)
diff --git a/libxfs/xfs_metadir.h b/libxfs/xfs_metadir.h
index a795a2d0e3fe..e434b9d1c932 100644
--- a/libxfs/xfs_metadir.h
+++ b/libxfs/xfs_metadir.h
@@ -32,9 +32,6 @@ int xfs_metadir_load(struct xfs_trans *tp, struct xfs_inode *dp,
const char *path, enum xfs_metafile_type metafile_type,
struct xfs_inode **ipp);
-int xfs_metadir_start_create(struct xfs_metadir_update *upd);
-int xfs_metadir_create(struct xfs_metadir_update *upd, umode_t mode);
-
typedef int (*xfs_metadir_createfn)(struct xfs_metadir_update *upd, void *priv);
int xfs_metadir_create_file(struct xfs_metadir_update *upd, umode_t mode,
@@ -45,7 +42,6 @@ int xfs_metadir_start_link(struct xfs_metadir_update *upd);
int xfs_metadir_link(struct xfs_metadir_update *upd);
int xfs_metadir_commit(struct xfs_metadir_update *upd);
-void xfs_metadir_cancel(struct xfs_metadir_update *upd, int error);
int xfs_metadir_mkdir(struct xfs_inode *dp, const char *path,
struct xfs_inode **ipp);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 05/28] xfs: use kmalloc_objs() instead of kmalloc() in xfs_da_grow_inode_int
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (3 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 04/28] xfs: mark internal metadir file creation helpers static Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 06/28] xfs: remove spurious XBF_DONE clearing on readahead validation failure Andrey Albershteyn
` (23 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Cihan Karadag <cihan.cihan@gmail.com>
Source kernel commit: 56aa9ef3c413cb13a373226f91a19358cd9f1266
Convert open-coded kmalloc() multiplication to the modern kmalloc_objs()
interface to improve type safety and prevent potential integer
overflows.
No functional changes are intended.
Signed-off-by: Cihan Karadag <cihan.cihan@gmail.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
include/kmem.h | 12 ++++++++++++
libxfs/xfs_da_btree.c | 3 +--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/include/kmem.h b/include/kmem.h
index 2c276e929c48..4363601ff682 100644
--- a/include/kmem.h
+++ b/include/kmem.h
@@ -138,4 +138,16 @@ static inline void *kmemdup(const void *src, size_t len, gfp_t gfp)
return p;
}
+/**
+ * kmalloc_objs - Allocate an array of the given type
+ * @VAR_OR_TYPE: Variable or type to allocate an array of.
+ * @COUNT: How many elements in the array.
+ * @...: optional GFP flags for the allocation (GFP_KERNEL when not specified).
+ *
+ * Returns: newly allocated pointer to array of @VAR_OR_TYPE on success,
+ * or NULL on failure.
+ */
+#define kmalloc_objs(VAR_OR_TYPE, COUNT, ...) \
+ __alloc_objs(kmalloc, default_gfp(__VA_ARGS__), typeof(VAR_OR_TYPE), COUNT)
+
#endif
diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c
index 9debb95d86fa..f190c088591b 100644
--- a/libxfs/xfs_da_btree.c
+++ b/libxfs/xfs_da_btree.c
@@ -2354,8 +2354,7 @@ xfs_da_grow_inode_int(
* If we didn't get it and the block might work if fragmented,
* try without the CONTIG flag. Loop until we get it all.
*/
- mapp = kmalloc(sizeof(*mapp) * count,
- GFP_KERNEL | __GFP_NOFAIL);
+ mapp = kmalloc_objs(*mapp, count, GFP_KERNEL | __GFP_NOFAIL);
for (b = *bno, mapi = 0; b < *bno + count; ) {
c = (int)(*bno + count - b);
nmap = min(XFS_BMAP_MAX_NMAP, c);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 06/28] xfs: remove spurious XBF_DONE clearing on readahead validation failure
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (4 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 05/28] xfs: use kmalloc_objs() instead of kmalloc() in xfs_da_grow_inode_int Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 07/28] xfs: hide b_flags manipulation from code outside of xfs_buf.c Andrey Albershteyn
` (22 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Christoph Hellwig <hch@lst.de>
Source kernel commit: 7a4eae80b5b3db8d68961af3707fd56f2220cc29
Both callers of ->verify_read already do this, so don't duplicate the
flag manipulation.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_dquot_buf.c | 8 +++-----
libxfs/xfs_inode_buf.c | 15 ++++++++-------
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c
index 21e74d6d17d9..e4599a084be5 100644
--- a/libxfs/xfs_dquot_buf.c
+++ b/libxfs/xfs_dquot_buf.c
@@ -251,8 +251,8 @@ xfs_dquot_buf_read_verify(
/*
* readahead errors are silent and simply leave the buffer as !done so a real
* read will then be run with the xfs_dquot_buf_ops verifier. See
- * xfs_inode_buf_verify() for why we use EIO and ~XBF_DONE here rather than
- * reporting the failure.
+ * xfs_inode_buf_verify() for why we use EIO here rather than reporting the
+ * failure.
*/
static void
xfs_dquot_buf_readahead_verify(
@@ -261,10 +261,8 @@ xfs_dquot_buf_readahead_verify(
struct xfs_mount *mp = bp->b_mount;
if (!xfs_dquot_buf_verify_crc(mp, bp, true) ||
- xfs_dquot_buf_verify(mp, bp, true) != NULL) {
+ xfs_dquot_buf_verify(mp, bp, true) != NULL)
xfs_buf_ioerror(bp, -EIO);
- bp->b_flags &= ~XBF_DONE;
- }
}
/*
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 8ea12f82ad81..6fff9bbd39ab 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -27,12 +27,14 @@
* has not had the inode cores stamped into it. Hence for readahead, the buffer
* may be potentially invalid.
*
- * If the readahead buffer is invalid, we need to mark it with an error and
- * clear the DONE status of the buffer so that a followup read will re-read it
- * from disk. We don't report the error otherwise to avoid warnings during log
- * recovery and we don't get unnecessary panics on debug kernels. We use EIO here
- * because all we want to do is say readahead failed; there is no-one to report
- * the error to, so this will distinguish it from a non-ra verifier failure.
+ * If the readahead buffer is invalid, we need to mark it with an error so that a
+ * followup read will re-read it from disk.
+ *
+ * We don't report the error otherwise to avoid warnings during log recovery and
+ * we don't get unnecessary panics on debug kernels. Use EIO here because all
+ * we want to do is say readahead failed; there is no-one to report the error
+ * to, so this will distinguish it from a non-ra verifier failure.
+ *
* Changes to this readahead error behaviour also need to be reflected in
* xfs_dquot_buf_readahead_verify().
*/
@@ -62,7 +64,6 @@ xfs_inode_buf_verify(
if (unlikely(!di_ok ||
XFS_TEST_ERROR(mp, XFS_ERRTAG_ITOBP_INOTOBP))) {
if (readahead) {
- bp->b_flags &= ~XBF_DONE;
xfs_buf_ioerror(bp, -EIO);
return;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 07/28] xfs: hide b_flags manipulation from code outside of xfs_buf.c
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (5 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 06/28] xfs: remove spurious XBF_DONE clearing on readahead validation failure Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 08/28] xfs: validate attr entry pointer before field access Andrey Albershteyn
` (21 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Christoph Hellwig <hch@lst.de>
Source kernel commit: 9f224de410d7efafc44ce1880aabd0101aa8688f
Add helpers for the remaining buffer flags manipulation not done in the
core buffer cache code.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_btree_staging.c | 7 +++----
libxfs/xfs_ialloc.c | 2 +-
libxfs/xfs_platform.h | 5 +++++
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/libxfs/xfs_btree_staging.c b/libxfs/xfs_btree_staging.c
index c3c7ea54895a..7314dab4bcfb 100644
--- a/libxfs/xfs_btree_staging.c
+++ b/libxfs/xfs_btree_staging.c
@@ -248,11 +248,10 @@ xfs_btree_bload_drop_buf(
return 0;
/*
- * Mark this buffer XBF_DONE (i.e. uptodate) so that a subsequent
- * xfs_buf_read will not pointlessly reread the contents from the disk.
+ * Mark this buffer uptodate so that a subsequent xfs_buf_read will
+ * not pointlessly reread the contents from the disk.
*/
- bp->b_flags |= XBF_DONE;
-
+ xfs_buf_set_uptodate(bp);
xfs_buf_delwri_queue_here(bp, buffers_list);
xfs_buf_relse(bp);
*bpp = NULL;
diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c
index a064289e1634..912b796bf5b6 100644
--- a/libxfs/xfs_ialloc.c
+++ b/libxfs/xfs_ialloc.c
@@ -412,7 +412,7 @@ xfs_ialloc_inode_init(
xfs_trans_ordered_buf(tp, fbuf);
}
} else {
- fbuf->b_flags |= XBF_DONE;
+ xfs_buf_set_uptodate(fbuf);
xfs_buf_delwri_queue(fbuf, buffer_list);
xfs_buf_relse(fbuf);
}
diff --git a/libxfs/xfs_platform.h b/libxfs/xfs_platform.h
index 4f4990a20dad..c6787ee4c83c 100644
--- a/libxfs/xfs_platform.h
+++ b/libxfs/xfs_platform.h
@@ -314,6 +314,11 @@ xfs_buf_incore(
void __xfs_buf_mark_corrupt(struct xfs_buf *bp, xfs_failaddr_t fa);
#define xfs_buf_mark_corrupt(bp) __xfs_buf_mark_corrupt((bp), __this_address)
+static inline void xfs_buf_set_uptodate(struct xfs_buf *bp)
+{
+ /* does nothing, XBF_DONE is not LIBXFS_B_UPTODATE */
+}
+
static inline void
xfs_buf_readahead(
struct xfs_buftarg *target,
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 08/28] xfs: validate attr entry pointer before field access
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (6 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 07/28] xfs: hide b_flags manipulation from code outside of xfs_buf.c Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 09/28] xfs: don't hold buffer locks across sync transaction commit in xfs_sync_sb_buf Andrey Albershteyn
` (20 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Hongling Zeng <zenghongling@kylinos.cn>
Source kernel commit: b7eea80be25f3334f131d52982b3131aba77b97d
xfs_attr3_leaf_verify_entry() accesses lentry/rentry fields (namelen,
valuelen) before checking if the entry pointer itself is within bounds.
If nameidx is crafted to point near the end of the buffer, these field
accesses can read out-of-bounds before the bounds check at
name_end > buf_end is performed.
Add explicit bounds checks for entry pointers before accessing their
fields. Use offsetof() to check that the start of the flexible array
member (nameval/name) is within bounds, which ensures all preceding
fields are safe to access.
Fixes: c84760659dcf2 ("xfs: check attribute leaf block structure")
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_attr_leaf.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index 86c5c09a5db4..b6288395f853 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -325,6 +325,13 @@ xfs_attr3_leaf_verify_entry(
*/
if (ent->flags & XFS_ATTR_LOCAL) {
lentry = xfs_attr3_leaf_name_local(leaf, idx);
+
+ /* Validate lentry pointer is within bounds before field access */
+ if ((char *)lentry >= buf_end)
+ return __this_address;
+ if ((char *)lentry + offsetof(struct xfs_attr_leaf_name_local, nameval) > buf_end)
+ return __this_address;
+
namesize = xfs_attr_leaf_entsize_local(lentry->namelen,
be16_to_cpu(lentry->valuelen));
name_end = (char *)lentry + namesize;
@@ -332,6 +339,13 @@ xfs_attr3_leaf_verify_entry(
return __this_address;
} else {
rentry = xfs_attr3_leaf_name_remote(leaf, idx);
+
+ /* Validate rentry pointer is within bounds before field access */
+ if ((char *)rentry >= buf_end)
+ return __this_address;
+ if ((char *)rentry + offsetof(struct xfs_attr_leaf_name_remote, name) > buf_end)
+ return __this_address;
+
namesize = xfs_attr_leaf_entsize_remote(rentry->namelen);
name_end = (char *)rentry + namesize;
if (rentry->namelen == 0)
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 09/28] xfs: don't hold buffer locks across sync transaction commit in xfs_sync_sb_buf
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (7 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 08/28] xfs: validate attr entry pointer before field access Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 10/28] treewide: refresh kmalloc_obj() conversions Andrey Albershteyn
` (19 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Yun Zhou <yun.zhou@windriver.com>
Source kernel commit: 41a28c865d1d5843f8cb9e0af17a8f4d9e2961ff
xfs_sync_sb_buf() holds sb/rtsb buffer locks across a synchronous
xfs_trans_commit(), which flushes the CIL push workqueue internally.
If shutdown occurs during the CIL push, xfs_buf_item_unpin() needs to
lock these buffers to fail them, causing a deadlock:
setlabel: holds buf lock -> flush_workqueue(xfs-cil)
CIL push worker: xfs_buf_item_unpin -> xfs_buf_lock(same buf)
Remove the xfs_trans_bhold() calls so that commit releases the buffer
locks normally. After the sync commit, re-acquire the buffers via
mp->m_sb_bp / mp->m_rtsb_bp for the on-disk writeback.
Fixes: f7664b31975b ("xfs: implement online get/set fs label")
Reported-by: syzbot+837bcd54843dd6262f2f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=837bcd54843dd6262f2f
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/stubs/xfs_mount.h | 4 ++++
libxfs/xfs_rtgroup.h | 6 +++++-
libxfs/xfs_sb.c | 37 +++++++++++++++++--------------------
3 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/libxfs/stubs/xfs_mount.h b/libxfs/stubs/xfs_mount.h
index 0dea578ee3a5..5ccf2cf9544e 100644
--- a/libxfs/stubs/xfs_mount.h
+++ b/libxfs/stubs/xfs_mount.h
@@ -181,6 +181,10 @@ typedef struct xfs_mount {
uint64_t m_metafile_resv_target;
uint64_t m_metafile_resv_used;
uint64_t m_metafile_resv_avail;
+
+ /* Always NULL in userspace, do not call xfs_sync_sb_buf! */
+ struct xfs_buf *m_sb_bp;
+ struct xfs_buf *m_rtsb_bp;
} xfs_mount_t;
#define M_IGEO(mp) (&(mp)->m_ino_geo)
diff --git a/libxfs/xfs_rtgroup.h b/libxfs/xfs_rtgroup.h
index c0b9f9f2c413..fca2eb74908c 100644
--- a/libxfs/xfs_rtgroup.h
+++ b/libxfs/xfs_rtgroup.h
@@ -359,7 +359,11 @@ static inline int xfs_initialize_rtgroups(struct xfs_mount *mp,
# define xfs_rtgroup_unlock(rtg, gf) ((void)0)
# define xfs_rtgroup_trans_join(tp, rtg, gf) ((void)0)
# define xfs_update_rtsb(bp, sb_bp) ((void)0)
-# define xfs_log_rtsb(tp, sb_bp) (NULL)
+static inline struct xfs_buf *xfs_log_rtsb(struct xfs_trans *tp,
+ const struct xfs_buf *sb_bp)
+{
+ return NULL;
+}
# define xfs_rtgroup_get_geometry(rtg, rgeo) (-EOPNOTSUPP)
#endif /* CONFIG_XFS_RT */
diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c
index aae63ccdb6b5..9f5924660a77 100644
--- a/libxfs/xfs_sb.c
+++ b/libxfs/xfs_sb.c
@@ -1469,36 +1469,33 @@ xfs_sync_sb_buf(
bool update_rtsb)
{
struct xfs_trans *tp;
- struct xfs_buf *bp;
- struct xfs_buf *rtsb_bp = NULL;
int error;
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp);
if (error)
return error;
- bp = xfs_trans_getsb(tp);
xfs_log_sb(tp);
- xfs_trans_bhold(tp, bp);
- if (update_rtsb) {
- rtsb_bp = xfs_log_rtsb(tp, bp);
- if (rtsb_bp)
- xfs_trans_bhold(tp, rtsb_bp);
- }
+ if (update_rtsb)
+ xfs_log_rtsb(tp, xfs_trans_getsb(tp));
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp);
if (error)
- goto out;
- /*
- * write out the sb buffer to get the changes to disk
- */
- error = xfs_bwrite(bp);
- if (!error && rtsb_bp)
- error = xfs_bwrite(rtsb_bp);
-out:
- if (rtsb_bp)
- xfs_buf_relse(rtsb_bp);
- xfs_buf_relse(bp);
+ return error;
+
+ /* Re-acquire and write the sb and rtsb to disk. */
+ xfs_buf_lock(mp->m_sb_bp);
+ error = xfs_bwrite(mp->m_sb_bp);
+ xfs_buf_unlock(mp->m_sb_bp);
+ if (error)
+ return error;
+
+ if (update_rtsb && mp->m_rtsb_bp) {
+ xfs_buf_lock(mp->m_rtsb_bp);
+ error = xfs_bwrite(mp->m_rtsb_bp);
+ xfs_buf_unlock(mp->m_rtsb_bp);
+ }
+
return error;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 10/28] treewide: refresh kmalloc_obj() conversions
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (8 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 09/28] xfs: don't hold buffer locks across sync transaction commit in xfs_sync_sb_buf Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 11/28] xfs: fix exchange-range reflink flag clearing issue with INO1_WRITTEN Andrey Albershteyn
` (18 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Kees Cook <kees+treewide@kernel.org>
Source kernel commit: 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d
This is another run of the Coccinelle script for converting kmalloc()
family of allocations to kmalloc_obj() via the existing rules in
scripts/coccinelle/api/kmalloc_objs.cocci
This catches both the set of kmalloc() uses added since the first
kmalloc_obj() conversions in v7.0 and adds a large group missed in the
first pass due to Coccinelle not interacting well with the cleanup.h
scoped_...() family of macros[1]. I worked around this with spatch's
"--macro-file" argument to a file with all the scoped_...() macros mapped
to Coccinelle's YACFE_ITERATOR[2] as that was the closest viable control
flow indicator I could find.
Build tested allmodconfig on x86, arm64, arm, loongarch, mips, powerpc,
riscv, and s390 with no new warnings.
Link: https://lore.kernel.org/lkml/202609021314.8A9C0B8@keescook/ [1]
Link: https://github.com/coccinelle/coccinelle/blob/master/standard.h [2]
Signed-off-by: Kees Cook <kees+treewide@kernel.org>
---
include/kmem.h | 2 ++
libxfs/xfs_da_btree.c | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/kmem.h b/include/kmem.h
index 4363601ff682..c6c7b7ed37d1 100644
--- a/include/kmem.h
+++ b/include/kmem.h
@@ -108,6 +108,8 @@ static inline size_t __must_check size_mul(size_t factor1, size_t factor2)
#define kzalloc_obj(P, ...) \
__alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), 1)
+#define kzalloc_objs(P, COUNT, ...) \
+ __alloc_objs(kzalloc, default_gfp(__VA_ARGS__), typeof(P), COUNT)
#define kmalloc_obj(VAR_OR_TYPE, ...) \
__alloc_objs(kmalloc, default_gfp(__VA_ARGS__), typeof(VAR_OR_TYPE), 1)
diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c
index f190c088591b..7938d2324e87 100644
--- a/libxfs/xfs_da_btree.c
+++ b/libxfs/xfs_da_btree.c
@@ -2746,8 +2746,8 @@ xfs_dabuf_map(
* larger one that needs to be free by the caller.
*/
if (nirecs > 1) {
- map = kcalloc(nirecs, sizeof(struct xfs_buf_map),
- GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL);
+ map = kzalloc_objs(struct xfs_buf_map, nirecs,
+ GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL);
*mapp = map;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 11/28] xfs: fix exchange-range reflink flag clearing issue with INO1_WRITTEN
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (9 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 10/28] treewide: refresh kmalloc_obj() conversions Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 12/28] xfs: initialise error in xfs_defer_finish_one() Andrey Albershteyn
` (17 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling, Lin Jiapeng
From: Lin Jiapeng <ljp1205831794@gmail.com>
Source kernel commit: a23eca88448e52eb1a81549862df7adce794fafb
When exchanging two full-file ranges, xmi_can_exchange_reflink_flags()
can move the reflink inode flag from the file that currently has it to
the other file, as long as exactly one side is marked. This assumes
that the file contents, and therefore all shared extents, are exchanged.
That assumption is not true when XFS_EXCHMAPS_INO1_WRITTEN is set.
xfs_exchmaps_can_skip_mapping() can skip hole and unwritten mappings
from file1, so an exchange can complete without moving every mapping
that the earlier flag-swap decision accounted for. In that case the
post-operation cleanup can clear the reflink flag from an inode that
still owns shared written extents. Later writes then take the
non-reflink write path and may update blocks that should still have
been protected by CoW, which shows up as data corruption between
reflink-related files.
Fix this by disabling the reflink flag exchange whenever
XFS_EXCHMAPS_INO1_WRITTEN is requested. The contents exchange can still
proceed; the conservative outcome is that both inodes keep the reflink
flag. The regular reflink flag cleanup path can drop the extra flag
later once the inode no longer has shared extents.
Reported-by: Lin Jiapeng (TencentOS Red Team) <jiapenglin@tencent.com>
Fixes: 966ceafc7a43 ("xfs: create deferred log items for file mapping exchanges")
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Lin Jiapeng <jiapenglin@tencent.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_exchmaps.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/libxfs/xfs_exchmaps.c b/libxfs/xfs_exchmaps.c
index 114463c101d6..5380927a4abe 100644
--- a/libxfs/xfs_exchmaps.c
+++ b/libxfs/xfs_exchmaps.c
@@ -958,6 +958,16 @@ xmi_can_exchange_reflink_flags(
{
struct xfs_mount *mp = req->ip1->i_mount;
+ /*
+ * The INO1_WRITTEN optimization can skip exchanging hole and
+ * unwritten mappings, which means we cannot guarantee that all
+ * shared extents actually moved to the other file. Clearing the
+ * reflink flag of an inode that still holds shared extents breaks
+ * the CoW write path, so refuse to exchange the flags in that case.
+ */
+ if (req->flags & XFS_EXCHMAPS_INO1_WRITTEN)
+ return false;
+
/*
* The INO1_WRITTEN optimization can skip exchanging hole and
* unwritten mappings, which means we cannot guarantee that all
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 12/28] xfs: initialise error in xfs_defer_finish_one()
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (10 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 11/28] xfs: fix exchange-range reflink flag clearing issue with INO1_WRITTEN Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 13/28] xfs: give the deferred barrier op type a name Andrey Albershteyn
` (16 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling, Javier Tia
From: Javier Tia <javier@peridio.com>
Source kernel commit: 6176d21d7bd609632c5b7e87a3adb9be29ec1e72
xfs_defer_finish_one() declares error without an initialiser and only
assigns it inside the loop over dfp->dfp_work. When that list is empty
the loop body never runs, control falls through to the "Done with the
dfp, free it" path, and the function returns an indeterminate value.
An item-less pending item reaches this through xfs_defer_add_barrier(),
which xfs_reap_ag_blocks() uses on any CONFIG_XFS_ONLINE_REPAIR kernel.
xfs_defer_finish_noroll() treats any non-EAGAIN return as fatal, so a
non-zero stack value turns a successful barrier into a
SHUTDOWN_CORRUPT_INCORE in the middle of a repair. Zero is the correct
result: reaching the free path means the item loop drained without a
non-zero error.
Fixes: 3f3cec031099 ("xfs: force small EFIs for reaping btree extents")
Signed-off-by: Javier Tia <floss@jetm.me>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_defer.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libxfs/xfs_defer.c b/libxfs/xfs_defer.c
index ab1f81d8bcd2..4aa232fbd214 100644
--- a/libxfs/xfs_defer.c
+++ b/libxfs/xfs_defer.c
@@ -580,7 +580,7 @@ xfs_defer_finish_one(
const struct xfs_defer_op_type *ops = dfp->dfp_ops;
struct xfs_btree_cur *state = NULL;
struct list_head *li, *n;
- int error;
+ int error = 0;
trace_xfs_defer_pending_finish(tp->t_mountp, dfp);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 13/28] xfs: give the deferred barrier op type a name
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (11 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 12/28] xfs: initialise error in xfs_defer_finish_one() Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 14/28] xfs: report the error that made deferred work shut down the fs Andrey Albershteyn
` (15 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling, Javier Tia
From: Javier Tia <javier@peridio.com>
Source kernel commit: 91c15cee394e9958898ef1ed55d9ced4c26e2800
xfs_barrier_defer_type is the only xfs_defer_op_type with no .name.
Every other one carries a short string used for tracing and reporting:
attr, bmap, extent_free, agfl_free, rtextent_free, refcount,
rtrefcount, rmap, rtrmap and exchmaps.
That has been harmless because nothing dereferences the field, but it
leaves a NULL in a table where every other entry is populated, so the
first caller to print it gets "(null)" in the kernel and undefined
behaviour in the userspace libxfs build of this file, where xfs_alert
lands in fprintf. xfs_defer_add() already treats a missing member of
this table as worth shutting the filesystem down for, so an unpopulated
one is out of step with how the file handles its own ops tables.
Signed-off-by: Javier Tia <floss@jetm.me>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_defer.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libxfs/xfs_defer.c b/libxfs/xfs_defer.c
index 4aa232fbd214..6c247d73cf1d 100644
--- a/libxfs/xfs_defer.c
+++ b/libxfs/xfs_defer.c
@@ -226,6 +226,7 @@ xfs_defer_barrier_cancel_item(
}
static const struct xfs_defer_op_type xfs_barrier_defer_type = {
+ .name = "barrier",
.max_items = 1,
.create_intent = xfs_defer_barrier_create_intent,
.abort_intent = xfs_defer_barrier_abort_intent,
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 14/28] xfs: report the error that made deferred work shut down the fs
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (12 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 13/28] xfs: give the deferred barrier op type a name Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 15/28] xfs: correct the parent pointer space reservation comment Andrey Albershteyn
` (14 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling, Javier Tia
From: Javier Tia <javier@peridio.com>
Source kernel commit: d058f24b163a8d63866ac6bbe5f06b41aabe97d7
When a deferred operation fails and shuts the filesystem down,
xfs_defer_finish_noroll() reports neither the errno nor which operation
originated it, so the log cannot tell a transient -ENOSPC from real
corruption. Report the operation type, errno and remaining reservation.
trace_xfs_defer_finish_error() runs after xfs_force_shutdown(), which
BUGs under fs.xfs.panic_mask and so never fires for the first failure;
move it ahead of the shutdown and mirror it to xfs_alert() for systems
without tracing armed. Capture the op name while the item is live (dfp
is freed once its work list drains) and suppress the alert once the fs is
already down.
Signed-off-by: Javier Tia <floss@jetm.me>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_defer.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/libxfs/xfs_defer.c b/libxfs/xfs_defer.c
index 6c247d73cf1d..aaf643a2d842 100644
--- a/libxfs/xfs_defer.c
+++ b/libxfs/xfs_defer.c
@@ -653,6 +653,7 @@ xfs_defer_finish_noroll(
struct xfs_trans **tp)
{
struct xfs_defer_pending *dfp = NULL;
+ const char *what = "chain";
int error = 0;
LIST_HEAD(dop_pending);
LIST_HEAD(dop_paused);
@@ -702,9 +703,17 @@ xfs_defer_finish_noroll(
struct xfs_defer_pending, dfp_list);
if (!dfp)
break;
+ what = dfp->dfp_ops->name;
error = xfs_defer_finish_one(*tp, dfp);
if (error && error != -EAGAIN)
goto out_shutdown;
+ /*
+ * A finished item is no longer a candidate for a later
+ * failure. An -EAGAIN one is not finished, so it keeps the
+ * attribution across the roll that completes it.
+ */
+ if (!error)
+ what = "chain";
}
/* Requeue the paused items in the outgoing transaction. */
@@ -716,8 +725,12 @@ xfs_defer_finish_noroll(
out_shutdown:
list_splice_tail_init(&dop_paused, &dop_pending);
xfs_defer_trans_abort(*tp, &dop_pending);
- xfs_force_shutdown((*tp)->t_mountp, SHUTDOWN_CORRUPT_INCORE);
trace_xfs_defer_finish_error(*tp, error);
+ if (!xfs_is_shutdown((*tp)->t_mountp))
+ xfs_alert((*tp)->t_mountp,
+ "deferred %s work failed, error %d, %u blocks reserved",
+ what, error, (*tp)->t_blk_res);
+ xfs_force_shutdown((*tp)->t_mountp, SHUTDOWN_CORRUPT_INCORE);
xfs_defer_cancel_list((*tp)->t_mountp, &dop_pending);
xfs_defer_cancel(*tp);
return error;
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 15/28] xfs: correct the parent pointer space reservation comment
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (13 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 14/28] xfs: report the error that made deferred work shut down the fs Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 16/28] xfs: initialise args->total for parent pointer updates Andrey Albershteyn
` (13 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling, Javier Tia
From: Javier Tia <javier@peridio.com>
Source kernel commit: 6c0fc3cb4e879927b338b4fcb6de6a25c0a67608
The comment on xfs_parent_calc_space_res() claims parent pointers are
"always the first attr in an attr tree". They are not: a parent pointer
is recorded per dirent, so by the Nth hardlink the attr fork is already
in leaf or node format. The reservation is still correct, because
XFS_DAENTER_SPACE_RES() covers a split at every level of a maximum-depth
attr dabtree whatever format the fork is in, but anyone auditing a
shortfall here is led by the comment to look for a bug that is not
there.
Rewrite the comment to state what actually bounds the result, and record
why the double split allowance and the extent-add term differ from
xfs_attr_calc_size().
Signed-off-by: Javier Tia <floss@jetm.me>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_trans_space.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/libxfs/xfs_trans_space.c b/libxfs/xfs_trans_space.c
index 9b8f495c9049..c4cd547033e5 100644
--- a/libxfs/xfs_trans_space.c
+++ b/libxfs/xfs_trans_space.c
@@ -22,8 +22,23 @@ xfs_parent_calc_space_res(
unsigned int namelen)
{
/*
- * Parent pointers are always the first attr in an attr tree, and never
- * larger than a block
+ * A parent pointer is recorded per dirent, so an inode with N links
+ * carries N of them and the attr fork can already be in leaf or node
+ * format when one is added. That does not affect the reservation:
+ * XFS_DAENTER_SPACE_RES covers a split at every level of a
+ * maximum-depth attr dabtree, whatever format the fork is in now.
+ *
+ * The name is a dirent name and the value is a struct xfs_parent_rec,
+ * so the leaf entry is always local and never exceeds 272 bytes.
+ * Parent pointers require V5, hence a 1k minimum block size, so the
+ * entry always stays under half a block and this needs none of the
+ * double split allowance that xfs_attr_calc_size() makes.
+ *
+ * The second term hands a byte count to a macro whose parameter counts
+ * mappings, so it asks for more extent-add allowance than the single
+ * mapping a parent pointer adds - how much more depends on the block
+ * size. It over-reserves either way, which is why it is left alone:
+ * correcting the unit would shrink a reservation that is only generous.
*/
return XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK) +
XFS_NEXTENTADD_SPACE_RES(mp, namelen, XFS_ATTR_FORK);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 16/28] xfs: initialise args->total for parent pointer updates
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (14 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 15/28] xfs: correct the parent pointer space reservation comment Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 17/28] xfs: assert the reservation covers each da fork growth Andrey Albershteyn
` (12 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling, Javier Tia
From: Javier Tia <javier@peridio.com>
Source kernel commit: 8e4ebb6afaa34bd2e8ce52da231003d24111c2d6
xfs_parent_da_args_init() builds an xfs_da_args from a zeroed
xfs_parent_args (kmem_cache_zalloc), leaving args->total == 0.
xfs_da_grow_inode_int() treats that field as a running block reservation
and subtracts from it; because it is an xfs_extlen_t (uint32_t), the
first attr-fork growth wraps it to ~0U. That defeats the free-space
check in xfs_alloc_space_available(), and when it coincides with an AG
that has exactly zero available blocks the allocation is clamped to
maxlen 0 and returns -ENOSPC, which xfs_defer_finish_noroll() escalates
to a filesystem shutdown.
Set args->total the way the log recovery path does
(xfs_attri_recover_work(), xfs_attr_item.c:706), in the add and replace
paths that can grow the fork. Removals and lookups never grow it, so
they leave the field alone, matching that switch.
Fixes: b7c62d90c12c ("xfs: parent pointer attribute creation")
Signed-off-by: Javier Tia <floss@jetm.me>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_parent.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c
index 992263f810f8..0576424ed8f1 100644
--- a/libxfs/xfs_parent.c
+++ b/libxfs/xfs_parent.c
@@ -192,7 +192,7 @@ xfs_parent_addname(
const struct xfs_name *parent_name,
struct xfs_inode *child)
{
- int error;
+ int error, local;
error = xfs_parent_iread_extents(tp, child);
if (error)
@@ -202,6 +202,10 @@ xfs_parent_addname(
xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child,
I_INO(child), parent_name);
+ /* Growing the attr fork needs a real reservation in args->total. */
+ ppargs->args.total = xfs_attr_calc_size(&ppargs->args, &local);
+ ASSERT(local);
+
return xfs_attr_setname(&ppargs->args, 0);
}
@@ -238,7 +242,7 @@ xfs_parent_replacename(
const struct xfs_name *new_name,
struct xfs_inode *child)
{
- int error;
+ int error, local;
error = xfs_parent_iread_extents(tp, child);
if (error)
@@ -248,6 +252,10 @@ xfs_parent_replacename(
xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child,
I_INO(child), old_name);
+ /* Growing the attr fork needs a real reservation in args->total. */
+ ppargs->args.total = xfs_attr_calc_size(&ppargs->args, &local);
+ ASSERT(local);
+
xfs_inode_to_parent_rec(&ppargs->new_rec, new_dp);
ppargs->args.new_name = new_name->name;
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 17/28] xfs: assert the reservation covers each da fork growth
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (15 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 16/28] xfs: initialise args->total for parent pointer updates Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 18/28] xfs: fix the rtrmap and rtrefcount _maxlevels_ondisk functions Andrey Albershteyn
` (11 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling, Javier Tia
From: Javier Tia <javier@peridio.com>
Source kernel commit: 0fe77e57588b989450d668f7c978bb0264c5c340
xfs_da_grow_inode_int() subtracts the blocks it just allocated from
args->total, the caller's remaining block reservation. The subtraction
is unsigned, so a caller that reaches it with too small a total wraps
the field instead of failing, and every allocation afterwards runs with
a bogus reservation. Assert the remaining reservation still covers the
step, so an under-reserved or uninitialised total trips in debug builds
instead of silently wrapping.
Suggested-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Javier Tia <floss@jetm.me>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_da_btree.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c
index 7938d2324e87..8cbdd6574755 100644
--- a/libxfs/xfs_da_btree.c
+++ b/libxfs/xfs_da_btree.c
@@ -2384,6 +2384,7 @@ xfs_da_grow_inode_int(
}
/* account for newly allocated blocks in reserved blocks total */
+ ASSERT(args->total >= dp->i_nblocks - nblks);
args->total -= dp->i_nblocks - nblks;
out_free_map:
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 18/28] xfs: fix the rtrmap and rtrefcount _maxlevels_ondisk functions
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (16 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 17/28] xfs: assert the reservation covers each da fork growth Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 19/28] xfs: fix xfs_rtrmapbt_mem_cursor for non-rmap filesystems Andrey Albershteyn
` (10 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: "Darrick J. Wong" <djwong@kernel.org>
Source kernel commit: aa301322f72f82f26e4ba0826018d41388ab9896
The _maxlevels_ondisk functions are used to compute the size of
in-memory btree cursors for each btree type. Unfortunately, LOLLM
noticed that the rtrmap and rtrefcount versions of these functions
forget to account for the inode root, which means that we could access
beyond the end of the cursor given a sufficiently large btree. Fix
this.
Fixes: 9abe03a0e4f978 ("xfs: introduce realtime refcount btree ondisk definitions")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Assisted-by: LOLLM # finding obvious bugs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_rtrefcount_btree.c | 7 +++++--
libxfs/xfs_rtrmap_btree.c | 4 +++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/libxfs/xfs_rtrefcount_btree.c b/libxfs/xfs_rtrefcount_btree.c
index 22acc1411aac..e2950dbe2068 100644
--- a/libxfs/xfs_rtrefcount_btree.c
+++ b/libxfs/xfs_rtrefcount_btree.c
@@ -489,8 +489,11 @@ xfs_rtrefcountbt_maxlevels_ondisk(void)
minrecs[0] = xfs_rtrefcountbt_block_maxrecs(blocklen, true) / 2;
minrecs[1] = xfs_rtrefcountbt_block_maxrecs(blocklen, false) / 2;
- /* We need at most one record for every block in an rt group. */
- return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_RGBLOCKS);
+ /*
+ * We need at most one record for every block in an rt group, and
+ * one extra level for the inode root.
+ */
+ return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_RGBLOCKS) + 1;
}
int __init
diff --git a/libxfs/xfs_rtrmap_btree.c b/libxfs/xfs_rtrmap_btree.c
index c264bc5651c0..0cb2113d5b40 100644
--- a/libxfs/xfs_rtrmap_btree.c
+++ b/libxfs/xfs_rtrmap_btree.c
@@ -716,10 +716,12 @@ xfs_rtrmapbt_maxlevels_ondisk(void)
* happens, which means that we must compute the max height based on
* what the btree will look like if it consumes almost all the blocks
* in the data device due to maximal sharing factor.
+ *
+ * Add one extra level for the inode root.
*/
max_dblocks = -1U; /* max ag count */
max_dblocks *= XFS_MAX_CRC_AG_BLOCKS;
- return xfs_btree_space_to_height(minrecs, max_dblocks);
+ return xfs_btree_space_to_height(minrecs, max_dblocks) + 1;
}
int __init
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 19/28] xfs: fix xfs_rtrmapbt_mem_cursor for non-rmap filesystems
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (17 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 18/28] xfs: fix the rtrmap and rtrefcount _maxlevels_ondisk functions Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 20/28] xfs: preserve owner on in-memory btree creation Andrey Albershteyn
` (9 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: "Darrick J. Wong" <djwong@kernel.org>
Source kernel commit: 022d5f5fce7f0b6125d404eb74044e6238aef369
It's possible to construct an in-memory rtrmap btree for filesystems
that don't have the rmap feature enabled. The kernel doesn't do this,
but xfs_repair will, if asked to reindex a filesystem that has rtreflink
enabled but not rtrmap. Therefore, we must create the cursor with
enough levels to handle a maximally sized btree possible.
Note that the rtrmapbt btree cursor slab creates objects large enough to
handle xfs_rtrmap_maxlevels_ondisk() levels, so setting bc_nlevels to
the same value isn't costing us any extra memory.
Fixes: 4a61f12eb11958 ("xfs: create a shadow rmap btree during realtime rmap repair")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_rtrmap_btree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libxfs/xfs_rtrmap_btree.c b/libxfs/xfs_rtrmap_btree.c
index 0cb2113d5b40..a15e460a1ec7 100644
--- a/libxfs/xfs_rtrmap_btree.c
+++ b/libxfs/xfs_rtrmap_btree.c
@@ -618,7 +618,7 @@ xfs_rtrmapbt_mem_cursor(
struct xfs_btree_cur *cur;
cur = xfs_btree_alloc_cursor(mp, tp, &xfs_rtrmapbt_mem_ops,
- mp->m_rtrmap_maxlevels, xfs_rtrmapbt_cur_cache);
+ xfs_rtrmapbt_maxlevels_ondisk(), xfs_rtrmapbt_cur_cache);
cur->bc_mem.xfbtree = xfbt;
cur->bc_nlevels = xfbt->nlevels;
cur->bc_group = xfs_group_hold(rtg_group(rtg));
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 20/28] xfs: preserve owner on in-memory btree creation
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (18 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 19/28] xfs: fix xfs_rtrmapbt_mem_cursor for non-rmap filesystems Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 21/28] xfs: don't leak new_bp if xfs_btree_bload_drop_buf fails Andrey Albershteyn
` (8 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: "Darrick J. Wong" <djwong@kernel.org>
Source kernel commit: 5287e56cba3be4a64bff9f73bce5964fda2590dc
LOLLM points out a minor bug where a higher level function creating an
in-memory btree is required to pass in an owner number, but the creation
function erases that. In-memory btrees are ephemeral so this really
doesn't matter except for debugging. But let's fix this papercut.
Fixes: a095686a238352 ("xfs: support in-memory btrees")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Assisted-by: LOLLM # finding obvious bugs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_btree_mem.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libxfs/xfs_btree_mem.c b/libxfs/xfs_btree_mem.c
index 37136a70e56d..1d83a4251cee 100644
--- a/libxfs/xfs_btree_mem.c
+++ b/libxfs/xfs_btree_mem.c
@@ -117,6 +117,7 @@ xfbtree_init(
struct xfs_buftarg *btp,
const struct xfs_btree_ops *ops)
{
+ unsigned long long owner = xfbt->owner;
unsigned int blocklen = xfbtree_rec_bytes(mp, ops);
unsigned int keyptr_len;
int error;
@@ -133,6 +134,7 @@ xfbtree_init(
memset(xfbt, 0, sizeof(*xfbt));
xfbt->target = btp;
+ xfbt->owner = owner;
/* Set up min/maxrecs for this btree. */
keyptr_len = ops->key_len + sizeof(__be64);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 21/28] xfs: don't leak new_bp if xfs_btree_bload_drop_buf fails
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (19 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 20/28] xfs: preserve owner on in-memory btree creation Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 22/28] xfs: fix under-reservation of blocks when repairing sf directories Andrey Albershteyn
` (7 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: "Darrick J. Wong" <djwong@kernel.org>
Source kernel commit: f1930bc578095409c2dcfca6e4e898b24f0f0de6
LOLLM observes that in xfs_btree_bload_prep_block,
xfs_btree_bload_drop_buf can hit an IO error if writing the delwri
buffer list to disk fails. In this case, we fail to release new_bp,
which means we lose a locked buffer. Fix that.
Fixes: e069d549705e49 ("xfs: constrain dirty buffers while formatting a staged btree")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Assisted-by: LOLLM # finding obvious bugs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_btree_staging.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libxfs/xfs_btree_staging.c b/libxfs/xfs_btree_staging.c
index 7314dab4bcfb..561fd2c2e950 100644
--- a/libxfs/xfs_btree_staging.c
+++ b/libxfs/xfs_btree_staging.c
@@ -336,8 +336,10 @@ xfs_btree_bload_prep_block(
xfs_btree_set_sibling(cur, *blockp, &new_ptr, XFS_BB_RIGHTSIB);
ret = xfs_btree_bload_drop_buf(bbl, buffers_list, bpp);
- if (ret)
+ if (ret) {
+ xfs_buf_relse(new_bp);
return ret;
+ }
/* Initialize the new btree block. */
xfs_btree_init_block_cur(cur, new_bp, level, nr_this_block);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 22/28] xfs: fix under-reservation of blocks when repairing sf directories
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (20 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 21/28] xfs: don't leak new_bp if xfs_btree_bload_drop_buf fails Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 23/28] xfs: remove duplicate INO1_WRITTEN check Andrey Albershteyn
` (6 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: "Darrick J. Wong" <djwong@kernel.org>
Source kernel commit: 4d3c07591534517c633945c8d8e6526f10e3fabc
Whilst running QA on XFS for-next as of 7.3-rc2 with MKFS_OPTIONS="-n
size=8192", I observed the following (trimmed) dmesg splat:
XFS: Assertion failed: args->total >= dp->i_nblocks - nblks, file: fs/xfs/libxfs/xfs_da_btree.c, line: 2387
WARNING: fs/xfs/xfs_message.c:104 at assfail+0x46/0x4a [xfs], CPU#0: xfs_scrub/1426511
CPU: 0 UID: 0 PID: 1426511 Comm: xfs_scrub Tainted: G W 7.3.0-rc2-djwx #rc2 PREEMPT(lazy) 6e418570b606a39783b0e7e7b30dc407b965f9e8
Tainted: [W]=WARN
RIP: 0010:assfail+0x46/0x4a [xfs]
RSP: 0018:ffffc900010d7890 EFLAGS: 00010246
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 00000000ffffffd1
RDX: 0000000000000000 RSI: 0000000000000021 RDI: ffffffffa059fd38
RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
R10: 000000000000000a R11: 000000007fffffff R12: ffffc900010d7940
R13: ffff888368d8f980 R14: ffffc900010d7a48 R15: ffffc900010d78d0
FS: 00007f445c5ce680(0000) GS:ffff8884a97ea000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f443803b9a8 CR3: 0000000107a4b000 CR4: 00000000003506f0
Call Trace:
<TASK>
xfs_da_grow_inode_int+0x2e0/0x300 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xfs_dir2_grow_inode+0x6e/0x150 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xfs_dir2_sf_to_block+0x149/0x870 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xrep_dir_swap_prep+0xe2/0x110 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xrep_dir_swap+0xfb/0x2f0 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xrep_dir_rebuild_tree+0x99/0x100 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xrep_directory+0x83/0x1c0 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xrep_attempt+0x4f/0x1e0 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xfs_scrub_metadata+0x393/0x5b0 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xfs_ioc_scrubv_metadata+0x306/0x570 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
xfs_file_ioctl+0xa4f/0x1150 [xfs 5de2257e14108c136f11317e6bbb8ac77efd392c]
__x64_sys_ioctl+0x76/0xc0
do_syscall_64+0x7a/0x3b0
entry_SYSCALL_64_after_hwframe+0x4b/0x53
This is a consequence of commit 0fe77e57588b98, which added the
following assertion to xfs_da_grow_inode_int:
ASSERT(args->total >= dp->i_nblocks - nblks);
Tracing this back to xrep_dir_swap_prep, I noticed that the xfs_da_args
object that's passed to xfs_dir2_sf_to_block sets args->total to 1.
This is incorrect because mkfs set the directory block size to 8k and
the filesystem block size to 4k. In other words, args->total should be
2 here, not 1.
Dave Chinner tripped over the same problem with the same branch through
a different channel -- his test setup set the fs block size to 1k, in
which case the directory block size is still set to 4k. Here,
args->total should be 4.
Changing the assignment of args->total to sc->mp->m_dir_geo->fsbcount
makes the assertion go away, but that isn't a complete fix. In
xrep_tempexch_estimate, we also incorrectly assume that a shortform
conversion requires 1 fsblock when it should be m_dir_geo->fsbcount.
Without that, we can under-reserve space in the transaction and cause a
filesystem shutdown.
Note that the xfs_dabuf_nfsb helper will compute the correct value for
directories and xattr, so we use that instead of open-coding the logic.
Also fix xrep_xattr_swap_prep to assign args->total via xfs_dabuf_nfsb
to avoid one logic bomb if we ever support multi-fsblock attrs.
Cc: floss@jetm.me
Reported-by: dgc@kernel.org
Fixes: 629fdaf5f5b1b7 ("xfs: use atomic extent swapping to fix user file fork data")
Tripped-by: 0fe77e57588b98 ("xfs: assert the reservation covers each da fork growth")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_da_btree.c | 2 +-
libxfs/xfs_da_btree.h | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c
index 8cbdd6574755..3d02a0d7ba44 100644
--- a/libxfs/xfs_da_btree.c
+++ b/libxfs/xfs_da_btree.c
@@ -130,7 +130,7 @@ xfs_da_state_reset(
state->mp = state->args->dp->i_mount;
}
-static inline int xfs_dabuf_nfsb(struct xfs_mount *mp, int whichfork)
+inline int xfs_dabuf_nfsb(struct xfs_mount *mp, int whichfork)
{
if (whichfork == XFS_DATA_FORK)
return mp->m_dir_geo->fsbcount;
diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h
index afcf2d3c7a21..a718b1ceb0aa 100644
--- a/libxfs/xfs_da_btree.h
+++ b/libxfs/xfs_da_btree.h
@@ -244,4 +244,6 @@ xfs_failaddr_t xfs_da3_node_header_check(struct xfs_buf *bp, xfs_ino_t owner);
extern struct kmem_cache *xfs_da_state_cache;
+int xfs_dabuf_nfsb(struct xfs_mount *mp, int whichfork);
+
#endif /* __XFS_DA_BTREE_H__ */
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 23/28] xfs: remove duplicate INO1_WRITTEN check
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (21 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 22/28] xfs: fix under-reservation of blocks when repairing sf directories Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 24/28] xfs: fix typos and repeated words in comments Andrey Albershteyn
` (5 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Jiangshan Yi <yijiangshan@kylinos.cn>
Source kernel commit: ce2b91bebc7bc0495fe3ad5ee47e4977fbb77fc5
Commit a23eca88448e ("xfs: fix exchange-range reflink flag clearing
issue with INO1_WRITTEN") duplicated commit b2d5a81dae38 ("xfs: fix
exchange-range reflink flag clearing issue with INO1_WRITTEN"), so
xmi_can_exchange_reflink_flags() ended up with two identical
XFS_EXCHMAPS_INO1_WRITTEN checks. The second one is dead code,
since the first one already returned false. Remove it.
Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_exchmaps.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/libxfs/xfs_exchmaps.c b/libxfs/xfs_exchmaps.c
index 5380927a4abe..114463c101d6 100644
--- a/libxfs/xfs_exchmaps.c
+++ b/libxfs/xfs_exchmaps.c
@@ -958,16 +958,6 @@ xmi_can_exchange_reflink_flags(
{
struct xfs_mount *mp = req->ip1->i_mount;
- /*
- * The INO1_WRITTEN optimization can skip exchanging hole and
- * unwritten mappings, which means we cannot guarantee that all
- * shared extents actually moved to the other file. Clearing the
- * reflink flag of an inode that still holds shared extents breaks
- * the CoW write path, so refuse to exchange the flags in that case.
- */
- if (req->flags & XFS_EXCHMAPS_INO1_WRITTEN)
- return false;
-
/*
* The INO1_WRITTEN optimization can skip exchanging hole and
* unwritten mappings, which means we cannot guarantee that all
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 24/28] xfs: fix typos and repeated words in comments
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (22 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 23/28] xfs: remove duplicate INO1_WRITTEN check Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 25/28] xfs: don't let hidden_space go negative in xfs_metafile_resv_init Andrey Albershteyn
` (4 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Hemanth Selam <hemanth.selam@gmail.com>
Source kernel commit: 2f3c2a6f963e57cf4f0f34cbf24ab11abb64d118
Correct ten misspellings and eight accidentally doubled words in
comments. No code changes.
The doubled word in xfs_zone_alloc.c was not a duplicate: "so that is is
reused" is "it is" misspelt, so that one reads "so that it is reused"
rather than dropping a word.
Signed-off-by: Hemanth Selam <hemanth.selam@gmail.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_ag.h | 2 +-
libxfs/xfs_alloc.c | 4 ++--
libxfs/xfs_attr_leaf.c | 2 +-
libxfs/xfs_errortag.h | 2 +-
libxfs/xfs_exchmaps.c | 2 +-
libxfs/xfs_format.h | 2 +-
libxfs/xfs_inode_buf.c | 2 +-
7 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/libxfs/xfs_ag.h b/libxfs/xfs_ag.h
index fd22fe598931..ee636b66a72f 100644
--- a/libxfs/xfs_ag.h
+++ b/libxfs/xfs_ag.h
@@ -207,7 +207,7 @@ xfs_perag_next(
}
/*
- * Per-ag geometry infomation and validation
+ * Per-ag geometry information and validation
*/
xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c
index d99602bcc16f..f762dcce8d13 100644
--- a/libxfs/xfs_alloc.c
+++ b/libxfs/xfs_alloc.c
@@ -3487,7 +3487,7 @@ xfs_alloc_read_agf(
}
/*
- * Pre-proces allocation arguments to set initial state that we don't require
+ * Pre-process allocation arguments to set initial state that we don't require
* callers to set up correctly, as well as bounds check the allocation args
* that are set up.
*/
@@ -3608,7 +3608,7 @@ xfs_alloc_vextent_finish(
* ABBA AGF deadlocks because a future allocation attempt in this
* transaction may attempt to lock a lower number AGF.
*
- * We can't release the AGF until the transaction is commited, so at
+ * We can't release the AGF until the transaction is committed, so at
* this point we must update the "first allocation" tracker to point at
* this AG if the tracker is empty or points to a lower AG. This allows
* the next allocation attempt to be modified appropriately to avoid
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index b6288395f853..2c80f4fd0b78 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -1715,7 +1715,7 @@ xfs_attr3_leaf_add_work(
/*
* This freemap entry starts at the old end of the
* leaf entry array, so we need to adjust its base
- * upward to accomodate the larger array.
+ * upward to accommodate the larger array.
*/
diff = sizeof(struct xfs_attr_leaf_entry);
} else if (ichdr->freemap[i].size > 0 &&
diff --git a/libxfs/xfs_errortag.h b/libxfs/xfs_errortag.h
index 6de207fed2d8..f0c83f1f0b3b 100644
--- a/libxfs/xfs_errortag.h
+++ b/libxfs/xfs_errortag.h
@@ -83,7 +83,7 @@
#define XFS_RANDOM_DEFAULT 100
/*
- * Table of errror injection knobs. The parameters to the XFS_ERRTAG macro are:
+ * Table of error injection knobs. The parameters to the XFS_ERRTAG macro are:
* 1. The XFS_ERRTAG_ flag but without the prefix;
* 2. The name of the sysfs knob; and
* 3. The default value for the knob.
diff --git a/libxfs/xfs_exchmaps.c b/libxfs/xfs_exchmaps.c
index 114463c101d6..9562784dd53d 100644
--- a/libxfs/xfs_exchmaps.c
+++ b/libxfs/xfs_exchmaps.c
@@ -394,7 +394,7 @@ xfs_exchmaps_one_step(
/*
* Re-add both mappings. We exchange the file offsets between the two
* maps and add the opposite map, which has the effect of filling the
- * logical offsets we just unmapped, but with with the physical mapping
+ * logical offsets we just unmapped, but with the physical mapping
* information exchanged.
*/
swap(irec1->br_startoff, irec2->br_startoff);
diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h
index dd0ed046fbe9..1a7a7e60a170 100644
--- a/libxfs/xfs_format.h
+++ b/libxfs/xfs_format.h
@@ -1051,7 +1051,7 @@ enum xfs_dinode_fmt {
* block is 1KB in size.
*
* With XFS_MAX_EXTCNT_DATA_FORK_SMALL representing maximum extent count and
- * with 1KB sized blocks, a file can reach upto,
+ * with 1KB sized blocks, a file can reach up to,
* 1KB * (2^31) = 2TB
*
* This is much larger than the theoretical maximum size of a directory
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index 6fff9bbd39ab..02a56321059b 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -624,7 +624,7 @@ xfs_dinode_verify(
* have di_nlink track the link count, even if the actual filesystem
* only supported V1 inodes (i.e. di_onlink). When writing out the
* ondisk inode, it would set both the ondisk di_nlink and di_onlink to
- * the the incore di_nlink value, which is why we cannot check for
+ * the incore di_nlink value, which is why we cannot check for
* di_nlink==0 on a V1 inode. V2/3 inodes would get written out with
* di_onlink==0, so we can check that.
*/
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 25/28] xfs: don't let hidden_space go negative in xfs_metafile_resv_init
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (23 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 24/28] xfs: fix typos and repeated words in comments Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 26/28] xfs: fix wild memcpy access when formatting ondisk rtrefcount btree roots Andrey Albershteyn
` (3 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: "Darrick J. Wong" <djwong@kernel.org>
Source kernel commit: 476582d754cdc5110f806001417fea6c77824c13
LOLLM points out that if the amount of fdblocks that we can reserve for
a metadata btree file goes below the space already used by that file,
then the hidden_space subtraction can underflow, causing
xfs_dec_fdblocks to subtract a huge amount of space. We never want the
target to be less than the used sapce, so fix the logic that adjusts
dblocks_avail downwards.
Also fix an error in the adjacent comment.
Fixes: 1df8d75030b787 ("xfs: make metabtree reservations global")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Assisted-by: LOLLM # finding obvious bugs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_metafile.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libxfs/xfs_metafile.c b/libxfs/xfs_metafile.c
index 71f004e9dc64..1f54d39003c2 100644
--- a/libxfs/xfs_metafile.c
+++ b/libxfs/xfs_metafile.c
@@ -297,14 +297,14 @@ xfs_metafile_resv_init(
goto out_unlock;
/*
- * Space taken by the per-AG metadata btrees are accounted on-disk as
- * used space. We therefore only hide the space that is reserved but
- * not used by the trees.
+ * Space taken by metadata btrees are accounted on-disk as used space.
+ * We therefore only hide the space that is reserved but not used by
+ * the trees.
*/
if (used > target)
target = used;
else if (target > dblocks_avail)
- target = dblocks_avail;
+ target = max(dblocks_avail, used);
hidden_space = target - used;
error = xfs_dec_fdblocks(mp, hidden_space, true);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 26/28] xfs: fix wild memcpy access when formatting ondisk rtrefcount btree roots
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (24 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 25/28] xfs: don't let hidden_space go negative in xfs_metafile_resv_init Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 27/28] xfs: stop exchanging reflink flags when exchanging mappings Andrey Albershteyn
` (2 subsequent siblings)
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: "Darrick J. Wong" <djwong@kernel.org>
Source kernel commit: fe2f9135df43db849e74f03956d322ac20b59af7
LOLLM noticed that the inode btree root formatting methods copy too many
bytes -- there's only one set of keys in node blocks, not two. This
causes memory corruption of whatever's beyond the buffers.
Fixes: f0415af60f482a ("xfs: wire up a new metafile type for the realtime refcount")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Assisted-by: LOLLM # finding obvious bugs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_rtrefcount_btree.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libxfs/xfs_rtrefcount_btree.c b/libxfs/xfs_rtrefcount_btree.c
index e2950dbe2068..dcc89b8e149b 100644
--- a/libxfs/xfs_rtrefcount_btree.c
+++ b/libxfs/xfs_rtrefcount_btree.c
@@ -617,7 +617,7 @@ xfs_rtrefcountbt_from_disk(
fpp = xfs_rtrefcount_droot_ptr_addr(dblock, 1, maxrecs);
tpp = xfs_rtrefcount_broot_ptr_addr(mp, rblock, 1, rblocklen);
numrecs = be16_to_cpu(dblock->bb_numrecs);
- memcpy(tkp, fkp, 2 * sizeof(*fkp) * numrecs);
+ memcpy(tkp, fkp, sizeof(*fkp) * numrecs);
memcpy(tpp, fpp, sizeof(*fpp) * numrecs);
} else {
frp = xfs_rtrefcount_droot_rec_addr(dblock, 1);
@@ -703,7 +703,7 @@ xfs_rtrefcountbt_to_disk(
fpp = xfs_rtrefcount_broot_ptr_addr(mp, rblock, 1, rblocklen);
tpp = xfs_rtrefcount_droot_ptr_addr(dblock, 1, maxrecs);
numrecs = be16_to_cpu(rblock->bb_numrecs);
- memcpy(tkp, fkp, 2 * sizeof(*fkp) * numrecs);
+ memcpy(tkp, fkp, sizeof(*fkp) * numrecs);
memcpy(tpp, fpp, sizeof(*fpp) * numrecs);
} else {
frp = xfs_rtrefcount_rec_addr(rblock, 1);
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 27/28] xfs: stop exchanging reflink flags when exchanging mappings
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (25 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 26/28] xfs: fix wild memcpy access when formatting ondisk rtrefcount btree roots Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 28/28] xfs: fix exchange-range-to-eof file size exchange Andrey Albershteyn
2026-10-29 12:25 ` [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Christoph Hellwig
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: Norbert Szetei <norbert@doyensec.com>
Source kernel commit: d84d6c1a7f1e2de9e601703a326a4c1b7b421943
When an exchange covers both files from offset 0 to i_disk_size,
xmi_can_exchange_reflink_flags() assumes every mapping moved and hands
the reflink flag over to the other file.
That assumption is wrong. A file can still own shared blocks past
i_disk_size, e.g. after EXCHANGE_RANGE_TO_EOF sets a smaller size
without unmapping anything. The flag is cleared anyway, and the next
write to such a block happens in place instead of CoW, corrupting the
other file that shares it.
Commit a23eca88448e ("xfs: fix exchange-range reflink flag clearing
issue with INO1_WRITTEN") fixed one instance of this. Rather than add
another special case, stop moving the flags.
xfs_exchmaps_ensure_reflink() already sets the flag on both inodes
before the exchange, so both just keep it.
Nothing sets CLEAR_INO{1,2}_REFLINK anymore. Intents logged by older
kernels may still carry them; recovery already masks them off, so they
stay in the log format mask and are ignored.
XFS_IOC_SWAPEXT has the same problem: it moves the reflink flag from
one inode to the other along with the extents. Just removing that is
not enough here: the exchange path flags both inodes up front in
xfs_exchmaps_ensure_reflink(), but swapext has no such step, so the
inode receiving the shared extents would be left without the flag.
Set it on both inodes instead, and make sure both have a CoW fork,
since an inode with the reflink flag is expected to have one.
The flag now stays until FALLOC_FL_UNSHARE_RANGE, xfs_scrub, or a
truncate to zero removes it.
Fixes: 966ceafc7a43 ("xfs: create deferred log items for file mapping exchanges")
Fixes: f0bc4d134b46 ("xfs: swap inode reflink flags when swapping inode extents")
Assisted-by: LLM
Signed-off-by: Norbert Szetei <norbert@doyensec.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_exchmaps.c | 80 ++---------------------------------------
libxfs/xfs_log_format.h | 4 +--
2 files changed, 4 insertions(+), 80 deletions(-)
diff --git a/libxfs/xfs_exchmaps.c b/libxfs/xfs_exchmaps.c
index 9562784dd53d..204d06ed091e 100644
--- a/libxfs/xfs_exchmaps.c
+++ b/libxfs/xfs_exchmaps.c
@@ -48,7 +48,7 @@ struct xfs_exchmaps_adjacent {
.right2 = { .br_startblock = HOLESTARTBLOCK }, \
}
-/* Information to reset reflink flag / CoW fork state after an exchange. */
+/* Information to reset CoW fork state after an exchange. */
/*
* If the reflink flag is set on either inode, make sure it has an incore CoW
@@ -126,9 +126,7 @@ xmi_has_more_exchange_work(const struct xfs_exchmaps_intent *xmi)
static inline bool
xmi_has_postop_work(const struct xfs_exchmaps_intent *xmi)
{
- return xmi->xmi_flags & (XFS_EXCHMAPS_CLEAR_INO1_REFLINK |
- XFS_EXCHMAPS_CLEAR_INO2_REFLINK |
- __XFS_EXCHMAPS_INO2_SHORTFORM);
+ return xmi->xmi_flags & __XFS_EXCHMAPS_INO2_SHORTFORM;
}
/* Check all mappings to make sure we can actually exchange them. */
@@ -524,18 +522,6 @@ free:
return error;
}
-/* Clear the reflink flag after an exchange. */
-static inline void
-xfs_exchmaps_clear_reflink(
- struct xfs_trans *tp,
- struct xfs_inode *ip)
-{
- trace_xfs_reflink_unset_inode_flag(ip);
-
- ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK;
- xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-}
-
/* Finish whatever work might come after an exchange operation. */
static int
xfs_exchmaps_do_postop_work(
@@ -556,16 +542,6 @@ xfs_exchmaps_do_postop_work(
return error;
}
- if (xmi->xmi_flags & XFS_EXCHMAPS_CLEAR_INO1_REFLINK) {
- xfs_exchmaps_clear_reflink(tp, xmi->xmi_ip1);
- xmi->xmi_flags &= ~XFS_EXCHMAPS_CLEAR_INO1_REFLINK;
- }
-
- if (xmi->xmi_flags & XFS_EXCHMAPS_CLEAR_INO2_REFLINK) {
- xfs_exchmaps_clear_reflink(tp, xmi->xmi_ip2);
- xmi->xmi_flags &= ~XFS_EXCHMAPS_CLEAR_INO2_REFLINK;
- }
-
return 0;
}
@@ -947,46 +923,13 @@ xfs_exchmaps_intent_destroy_cache(void)
}
/*
- * Decide if we will exchange the reflink flags between the two files after the
- * exchange. The only time we want to do this is if we're exchanging all
- * mappings under EOF and the inode reflink flags have different states.
+ * Allocate and initialize a new incore intent item from a request.
*/
-static inline bool
-xmi_can_exchange_reflink_flags(
- const struct xfs_exchmaps_req *req,
- unsigned int reflink_state)
-{
- struct xfs_mount *mp = req->ip1->i_mount;
-
- /*
- * The INO1_WRITTEN optimization can skip exchanging hole and
- * unwritten mappings, which means we cannot guarantee that all
- * shared extents actually moved to the other file. Clearing the
- * reflink flag of an inode that still holds shared extents breaks
- * the CoW write path, so refuse to exchange the flags in that case.
- */
- if (req->flags & XFS_EXCHMAPS_INO1_WRITTEN)
- return false;
-
- if (hweight32(reflink_state) != 1)
- return false;
- if (req->startoff1 != 0 || req->startoff2 != 0)
- return false;
- if (req->blockcount != XFS_B_TO_FSB(mp, req->ip1->i_disk_size))
- return false;
- if (req->blockcount != XFS_B_TO_FSB(mp, req->ip2->i_disk_size))
- return false;
- return true;
-}
-
-
-/* Allocate and initialize a new incore intent item from a request. */
struct xfs_exchmaps_intent *
xfs_exchmaps_init_intent(
const struct xfs_exchmaps_req *req)
{
struct xfs_exchmaps_intent *xmi;
- unsigned int rs = 0;
xmi = kmem_cache_zalloc(xfs_exchmaps_intent_cache,
GFP_NOFS | __GFP_NOFAIL);
@@ -1010,23 +953,6 @@ xfs_exchmaps_init_intent(
xmi->xmi_isize2 = req->ip1->i_disk_size;
}
- /* Record the state of each inode's reflink flag before the op. */
- if (xfs_is_reflink_inode(req->ip1))
- rs |= 1;
- if (xfs_is_reflink_inode(req->ip2))
- rs |= 2;
-
- /*
- * Figure out if we're clearing the reflink flags (which effectively
- * exchanges them) after the operation.
- */
- if (xmi_can_exchange_reflink_flags(req, rs)) {
- if (rs & 1)
- xmi->xmi_flags |= XFS_EXCHMAPS_CLEAR_INO1_REFLINK;
- if (rs & 2)
- xmi->xmi_flags |= XFS_EXCHMAPS_CLEAR_INO2_REFLINK;
- }
-
if (S_ISDIR(VFS_I(xmi->xmi_ip2)->i_mode) ||
S_ISLNK(VFS_I(xmi->xmi_ip2)->i_mode))
xmi->xmi_flags |= __XFS_EXCHMAPS_INO2_SHORTFORM;
diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h
index a4e1b3eb425c..6e620380d5dc 100644
--- a/libxfs/xfs_log_format.h
+++ b/libxfs/xfs_log_format.h
@@ -927,10 +927,8 @@ struct xfs_xmi_log_format {
*/
#define XFS_EXCHMAPS_INO1_WRITTEN (1ULL << 2)
-/* Clear the reflink flag from inode1 after the operation. */
+/* No longer set, but older intents may carry them; keep them valid. */
#define XFS_EXCHMAPS_CLEAR_INO1_REFLINK (1ULL << 3)
-
-/* Clear the reflink flag from inode2 after the operation. */
#define XFS_EXCHMAPS_CLEAR_INO2_REFLINK (1ULL << 4)
#define XFS_EXCHMAPS_LOGGED_FLAGS (XFS_EXCHMAPS_ATTR_FORK | \
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 28/28] xfs: fix exchange-range-to-eof file size exchange
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (26 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 27/28] xfs: stop exchanging reflink flags when exchanging mappings Andrey Albershteyn
@ 2026-10-29 12:06 ` Andrey Albershteyn
2026-10-29 12:25 ` [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Christoph Hellwig
28 siblings, 0 replies; 30+ messages in thread
From: Andrey Albershteyn @ 2026-10-29 12:06 UTC (permalink / raw)
To: linux-xfs
Cc: cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong, floss, hch,
hemanth.selam, jiapenglin, johannes.thumshirn, kees+treewide,
norbert, syzbot+837bcd54843dd6262f2f, yijiangshan, yun.zhou,
zenghongling
From: "Darrick J. Wong" <djwong@kernel.org>
Source kernel commit: 7dfb218c829c1acb626e0fe92c5fddb9a26a03e9
Norbert Szetei posted a patch containing an incomplete description of a
bug in XFS_IOC_EXCHANGE_RANGE's TO_EOF flag. The bug tricks
exchange-range into modifying a file so that it has shared blocks
starting beyond EOF, which is never allowed because files never have
written data beyond EOF, and you can only share written data blocks.
This is key to all the incorrect behavior that follows.
Eventually I got from Norbert a description of what's going wrong:
> Fair. Here it is with physical block numbers, 4k blocks. peer is the file
> that gets rewritten and file1 is the one that ends up with the flag
> cleared.
>
> Start, nothing shared:
>
> peer size 4096 -> [100]
> file1 size 12288 -> [200] [201] [202]
> donor1 size 4096 -> [300]
> donor2 size 4096 -> [400]
>
> 1. FICLONERANGE peer's block into file1's middle slot:
>
> peer size 4096 -> [100]
> file1 size 12288 -> [200] [100] [202] reflink flag set
> ^^^^^ both files own block 100
>
> 2. XFS_IOC_EXCHANGE_RANGE file1 against donor1, file1_offset 0,
> file2_offset 8192, length 0, TO_EOF. One block is exchanged, and the sizes
> are exchanged with it:
>
> file1 size 4096 -> [200] [100] [300] reflink flag set
> ^^^^^^^^^^^ still owned, now past the size
> donor1 size 12288 -> [202]
>
> file1 says it is one block long while it still owns three. Nothing was
> unmapped. file2_offset is block 2, so this exchange cannot clear a flag.
>
> 3. XFS_IOC_EXCHANGE_RANGE file1 against donor2, both offsets 0, length 4096.
> By i_disk_size this is two one-block files exchanging everything, so
> xmi_can_exchange_reflink_flags() agrees and the flag is cleared:
>
> file1 size 4096 -> [400] [100] [300] reflink flag CLEARED
> donor2 size 4096 -> [200]
>
> Block 100 is still shared with peer.
>
> 4. pwrite(file1, 4096, 4096), which is file1's second slot, block 100.
> xfs_is_cow_inode(file1) is false, so no CoW:
>
> peer size 4096 -> [100] same block, new contents
>
> Block 100 is the only one that matters here. PoC below, it reads a file
> called peer in the current directory. The filesystem needs reflink and
> exchange-range, which mkfs.xfs 7.x turns on by default.
So yes, TO_EOF is screwing up the file size even if it's actually
exchanging the data block correctly. The following is the intended
behavior of XFS_EXCHANGE_RANGE_TO_EOF, as described by its manpage:
"Ignore the length parameter. All bytes in file1_fd from file1_offset
to EOF are moved to file2_fd, and file2's size is set to
(file2_offset+(file1_length-file1_offset)). Meanwhile, all bytes in
file2 from file2_offset to EOF are moved to file1 and file1's size is
set to (file1_offset+(file2_length-file2_offset))."
In other words, if we only exchange a portion of the file data, then we
should only exchange the portion of the file size that relates to the
exchanged data. Unfortunately, the code swaps the ondisk file size and
the incore file sizes, which is incorrect if the caller passes in a
nonzero offset.
Having confused the file sizes, the PoC uses a second exchange-range
call on what looks like a non-reflinked single-block file. Because the
file size is set incorrectly, exchange-range thinks it's exchanging the
full contents of two files and clears the reflink flag on the broken
file. That enables an extending write of the broken file to rewrite the
shared block that's just past EOF. This has become known colloquially
as refluxfs.
Once the file sizes are set correctly, the second exchange-range no
longer thinks that it's doing a full-contents swap, so it won't clear
the reflink flag on either of its file arguments.
Norbert followed up to an earlier version of this patch with a second
complaint about us not handling the i_disk_size state correctly:
> The offsets are bounded against the incore i_size but subtracted from
> the ondisk i_disk_size, so a file that has not been written back gives
> xmi_isize1 = 0 + (0 - 12288).
>
> For instance, you can do:
>
> $ xfs_io -f -c "pwrite -q 0 4096" -c fsync file1
> $ xfs_io -f -c "pwrite -q 0 12288" \
> -c "exchangerange -s 0 -d 12288 file1" dirty
> $ stat -c %s file1
> 0
> $ stat -c %i file1
> 131
> $ sudo xfs_io -r -c "bulkstat_single 131" . | grep bs_size
> bs_size = 18446744073709539328
That's wrong, and the new file size update logic depends on the ondisk
i_disk_size matching the incore i_size, so flush the pagecache as needed
to push it upwards.
Link: https://lore.kernel.org/linux-xfs/1E196589-DEBE-40AC-AFEA-D420DAAB067F@doyensec.com/
Reported-by: Norbert Szetei <norbert@doyensec.com>
Fixes: 966ceafc7a4371 ("xfs: create deferred log items for file mapping exchanges")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_exchmaps.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/libxfs/xfs_exchmaps.c b/libxfs/xfs_exchmaps.c
index 204d06ed091e..99bf3e956108 100644
--- a/libxfs/xfs_exchmaps.c
+++ b/libxfs/xfs_exchmaps.c
@@ -930,6 +930,7 @@ xfs_exchmaps_init_intent(
const struct xfs_exchmaps_req *req)
{
struct xfs_exchmaps_intent *xmi;
+ struct xfs_mount *mp = req->ip1->i_mount;
xmi = kmem_cache_zalloc(xfs_exchmaps_intent_cache,
GFP_NOFS | __GFP_NOFAIL);
@@ -947,10 +948,18 @@ xfs_exchmaps_init_intent(
return xmi;
}
+ /*
+ * If the caller wanted, set each file's size to that file's exchange
+ * offset + length exchanged from the other file because the ranges in
+ * each file might be different lengths.
+ */
if (req->flags & XFS_EXCHMAPS_SET_SIZES) {
+ loff_t off1 = XFS_FSB_TO_B(mp, xmi->xmi_startoff1);
+ loff_t off2 = XFS_FSB_TO_B(mp, xmi->xmi_startoff2);
+
xmi->xmi_flags |= XFS_EXCHMAPS_SET_SIZES;
- xmi->xmi_isize1 = req->ip2->i_disk_size;
- xmi->xmi_isize2 = req->ip1->i_disk_size;
+ xmi->xmi_isize1 = off1 + (req->ip2->i_disk_size - off2);
+ xmi->xmi_isize2 = off2 + (req->ip1->i_disk_size - off1);
}
if (S_ISDIR(VFS_I(xmi->xmi_ip2)->i_mode) ||
--
2.54.0
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 00/28] xfsprogs: libxfs sync for v7.3
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
` (27 preceding siblings ...)
2026-10-29 12:06 ` [PATCH 28/28] xfs: fix exchange-range-to-eof file size exchange Andrey Albershteyn
@ 2026-10-29 12:25 ` Christoph Hellwig
28 siblings, 0 replies; 30+ messages in thread
From: Christoph Hellwig @ 2026-10-29 12:25 UTC (permalink / raw)
To: Andrey Albershteyn
Cc: linux-xfs, cem, cihan.cihan, cmaiolino, dchinner, dgc, djwong,
floss, hch, hemanth.selam, jiapenglin, johannes.thumshirn,
kees+treewide, norbert, syzbot+837bcd54843dd6262f2f, yijiangshan,
yun.zhou, zenghongling
From a quick look over all the changes not directly ported from the
kernel this looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2026-10-29 12:25 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 12:05 [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Andrey Albershteyn
2026-10-29 12:05 ` [PATCH 01/28] xfs: add xfs_metadir_create_file helper Andrey Albershteyn
2026-10-29 12:05 ` [PATCH 02/28] xfs: create quota metadir inodes using xfs_metadir_create_file Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 03/28] xfs: create rtgroup " Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 04/28] xfs: mark internal metadir file creation helpers static Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 05/28] xfs: use kmalloc_objs() instead of kmalloc() in xfs_da_grow_inode_int Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 06/28] xfs: remove spurious XBF_DONE clearing on readahead validation failure Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 07/28] xfs: hide b_flags manipulation from code outside of xfs_buf.c Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 08/28] xfs: validate attr entry pointer before field access Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 09/28] xfs: don't hold buffer locks across sync transaction commit in xfs_sync_sb_buf Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 10/28] treewide: refresh kmalloc_obj() conversions Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 11/28] xfs: fix exchange-range reflink flag clearing issue with INO1_WRITTEN Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 12/28] xfs: initialise error in xfs_defer_finish_one() Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 13/28] xfs: give the deferred barrier op type a name Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 14/28] xfs: report the error that made deferred work shut down the fs Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 15/28] xfs: correct the parent pointer space reservation comment Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 16/28] xfs: initialise args->total for parent pointer updates Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 17/28] xfs: assert the reservation covers each da fork growth Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 18/28] xfs: fix the rtrmap and rtrefcount _maxlevels_ondisk functions Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 19/28] xfs: fix xfs_rtrmapbt_mem_cursor for non-rmap filesystems Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 20/28] xfs: preserve owner on in-memory btree creation Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 21/28] xfs: don't leak new_bp if xfs_btree_bload_drop_buf fails Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 22/28] xfs: fix under-reservation of blocks when repairing sf directories Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 23/28] xfs: remove duplicate INO1_WRITTEN check Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 24/28] xfs: fix typos and repeated words in comments Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 25/28] xfs: don't let hidden_space go negative in xfs_metafile_resv_init Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 26/28] xfs: fix wild memcpy access when formatting ondisk rtrefcount btree roots Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 27/28] xfs: stop exchanging reflink flags when exchanging mappings Andrey Albershteyn
2026-10-29 12:06 ` [PATCH 28/28] xfs: fix exchange-range-to-eof file size exchange Andrey Albershteyn
2026-10-29 12:25 ` [PATCH 00/28] xfsprogs: libxfs sync for v7.3 Christoph Hellwig
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.