[PATCH 6.18 040/752] gfs2: fiemap page fault fix

Sasha Levin
2026-02-28T17:48:43Z

From: Andreas Gruenbacher <agruenba@redhat.com>

[ Upstream commit e411d74cc5ba290f85d0dd5e4d1df8f1d6d975d2 ]

In gfs2_fiemap(), we are calling iomap_fiemap() while holding the inode
glock. This can lead to recursive glock taking if the fiemap buffer is
memory mapped to the same inode and accessing it triggers a page fault.

Fix by disabling page faults for iomap_fiemap() and faulting in the
buffer by hand if necessary.

Fixes xfstest generic/742.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/gfs2/inode.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 63d9fe7464344..03dd54fb7e8c8 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2192,6 +2192,14 @@ static int gfs2_getattr(struct mnt_idmap *idmap,
return 0;
}

+static bool fault_in_fiemap(struct fiemap_extent_info *fi)
+{
+ struct fiemap_extent __user *dest = fi->fi_extents_start;
+ size_t size = sizeof(*dest) * fi->fi_extents_max;
+
+ return fault_in_safe_writeable((char __user *)dest, size) == 0;
+}
+
static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len)
{
@@ -2201,14 +2209,22 @@ static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,

inode_lock_shared(inode);

+retry:
ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh);
if (ret)
goto out;

+ pagefault_disable();
ret = iomap_fiemap(inode, fieinfo, start, len, &gfs2_iomap_ops);
+ pagefault_enable();

gfs2_glock_dq_uninit(&gh);

+ if (ret == -EFAULT && fault_in_fiemap(fieinfo)) {
+ fieinfo->fi_extents_mapped = 0;
+ goto retry;
+ }
+
out:
inode_unlock_shared(inode);
return ret;
--
2.51.0