| From 584fba43d25e26ecd5ef96cd25b424dbb20b36d7 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 28 Oct 2021 11:53:10 -0500 |
| Subject: gfs2: release iopen glock early in evict |
| |
| From: Bob Peterson <rpeterso@redhat.com> |
| |
| [ Upstream commit 49462e2be119d38c5eb5759d0d1b712df3a41239 ] |
| |
| Before this patch, evict would clear the iopen glock's gl_object after |
| releasing the inode glock. In the meantime, another process could reuse |
| the same block and thus glocks for a new inode. It would lock the inode |
| glock (exclusively), and then the iopen glock (shared). The shared |
| locking mode doesn't provide any ordering against the evict, so by the |
| time the iopen glock is reused, evict may not have gotten to setting |
| gl_object to NULL. |
| |
| Fix that by releasing the iopen glock before the inode glock in |
| gfs2_evict_inode. |
| |
| Signed-off-by: Bob Peterson <rpeterso@redhat.com>gl_object |
| Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/gfs2/super.c | 14 +++++++------- |
| 1 file changed, 7 insertions(+), 7 deletions(-) |
| |
| diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c |
| index 6a355e1347d7f..d2b7ecbd1b150 100644 |
| --- a/fs/gfs2/super.c |
| +++ b/fs/gfs2/super.c |
| @@ -1438,13 +1438,6 @@ static void gfs2_evict_inode(struct inode *inode) |
| gfs2_ordered_del_inode(ip); |
| clear_inode(inode); |
| gfs2_dir_hash_inval(ip); |
| - if (ip->i_gl) { |
| - glock_clear_object(ip->i_gl, ip); |
| - 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; |
| - } |
| if (gfs2_holder_initialized(&ip->i_iopen_gh)) { |
| struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; |
| |
| @@ -1457,6 +1450,13 @@ static void gfs2_evict_inode(struct inode *inode) |
| gfs2_holder_uninit(&ip->i_iopen_gh); |
| gfs2_glock_put_eventually(gl); |
| } |
| + if (ip->i_gl) { |
| + glock_clear_object(ip->i_gl, ip); |
| + 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; |
| + } |
| } |
| |
| static struct inode *gfs2_alloc_inode(struct super_block *sb) |
| -- |
| 2.33.0 |
| |