mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-07-19 21:40:29 +02:00
gfs2: fiemap page fault fix
[ Upstream commit e411d74cc5 ]
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>
This commit is contained in:
committed by
Sasha Levin
parent
d791c544ef
commit
5d5d9ec957
@@ -2076,6 +2076,14 @@ static int gfs2_getattr(struct user_namespace *mnt_userns,
|
||||
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)
|
||||
{
|
||||
@@ -2085,14 +2093,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;
|
||||
|
||||
Reference in New Issue
Block a user