summaryrefslogtreecommitdiff
path: root/fs/gfs2
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2023-10-02 05:33:44 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-11-28 20:19:47 +0300
commit7f9b5e974cbb500ea88643b385913ab41cc6560b (patch)
treec8ad439afa528d4616fe8dd2bb7604eabb51275e /fs/gfs2
parent119565e566f91ff3588ffcd5812f0c8061586c6b (diff)
downloadlinux-7f9b5e974cbb500ea88643b385913ab41cc6560b.tar.xz
gfs2: fix an oops in gfs2_permission
[ Upstream commit 0abd1557e21c617bd13fc18f7725fc6363c05913 ] In RCU mode, we might race with gfs2_evict_inode(), which zeroes ->i_gl. Freeing of the object it points to is RCU-delayed, so if we manage to fetch the pointer before it's been replaced with NULL, we are fine. Check if we'd fetched NULL and treat that as "bail out and tell the caller to get out of RCU mode". Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/inode.c11
-rw-r--r--fs/gfs2/super.c2
2 files changed, 10 insertions, 3 deletions
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 0eac04507904..eb4bbe1728c0 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -1868,14 +1868,21 @@ int gfs2_permission(struct mnt_idmap *idmap, struct inode *inode,
{
struct gfs2_inode *ip;
struct gfs2_holder i_gh;
+ struct gfs2_glock *gl;
int error;
gfs2_holder_mark_uninitialized(&i_gh);
ip = GFS2_I(inode);
- if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
+ gl = rcu_dereference(ip->i_gl);
+ if (unlikely(!gl)) {
+ /* inode is getting torn down, must be RCU mode */
+ WARN_ON_ONCE(!(mask & MAY_NOT_BLOCK));
+ return -ECHILD;
+ }
+ if (gfs2_glock_is_locked_by_me(gl) == NULL) {
if (mask & MAY_NOT_BLOCK)
return -ECHILD;
- error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
+ error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
if (error)
return error;
}
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 02d93da21b2b..0dd5641990b9 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1550,7 +1550,7 @@ out:
wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE);
gfs2_glock_add_to_lru(ip->i_gl);
gfs2_glock_put_eventually(ip->i_gl);
- ip->i_gl = NULL;
+ rcu_assign_pointer(ip->i_gl, NULL);
}
}