Skip to content

Commit c412a97

Browse files
AstralBobAndreas Gruenbacher
authored andcommitted
gfs2: Use TRY lock in gfs2_inode_lookup for UNLINKED inodes
Before this patch, delete_work_func() would check for the GLF_DEMOTE flag on the iopen glock and if set, it would perform special processing. However, there was a race whereby the GLF_DEMOTE flag could be set by another process after the check. Then when it called gfs2_lookup_by_inum() which calls gfs2_inode_lookup(), it tried to lock the iopen glock in SH mode, but the GLF_DEMOTE flag prevented the request from being granted. But the iopen glock could never be demoted because that happens when the inode is evicted, and the evict was never completed because of the failed lookup. To fix that, change function gfs2_inode_lookup() so that when GFS2_BLKST_UNLINKED inodes are searched, it uses the LM_FLAG_TRY flag for the iopen glock. If the locking request fails, fail gfs2_inode_lookup() with -EAGAIN so that delete_work_func() can retry the operation later. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
1 parent 1c23f9e commit c412a97

File tree

2 files changed

+13
-5
lines changed

2 files changed

+13
-5
lines changed

fs/gfs2/glock.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,16 +1018,18 @@ static void delete_work_func(struct work_struct *work)
10181018
if (gfs2_queue_delete_work(gl, 5 * HZ))
10191019
return;
10201020
}
1021-
goto out;
10221021
}
10231022

10241023
inode = gfs2_lookup_by_inum(sdp, no_addr, gl->gl_no_formal_ino,
10251024
GFS2_BLKST_UNLINKED);
1026-
if (!IS_ERR_OR_NULL(inode)) {
1025+
if (IS_ERR(inode)) {
1026+
if (PTR_ERR(inode) == -EAGAIN &&
1027+
(gfs2_queue_delete_work(gl, 5 * HZ)))
1028+
return;
1029+
} else {
10271030
d_prune_aliases(inode);
10281031
iput(inode);
10291032
}
1030-
out:
10311033
gfs2_glock_put(gl);
10321034
}
10331035

fs/gfs2/inode.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
130130
if (inode->i_state & I_NEW) {
131131
struct gfs2_sbd *sdp = GFS2_SB(inode);
132132
struct gfs2_glock *io_gl;
133+
int extra_flags = 0;
133134

134135
error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE,
135136
&ip->i_gl);
@@ -141,9 +142,12 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
141142
if (unlikely(error))
142143
goto fail;
143144

144-
if (blktype != GFS2_BLKST_UNLINKED)
145+
if (blktype == GFS2_BLKST_UNLINKED)
146+
extra_flags |= LM_FLAG_TRY;
147+
else
145148
gfs2_cancel_delete_work(io_gl);
146-
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT,
149+
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED,
150+
GL_EXACT | extra_flags,
147151
&ip->i_iopen_gh);
148152
gfs2_glock_put(io_gl);
149153
if (unlikely(error))
@@ -210,6 +214,8 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
210214
return inode;
211215

212216
fail:
217+
if (error == GLR_TRYFAILED)
218+
error = -EAGAIN;
213219
if (gfs2_holder_initialized(&ip->i_iopen_gh))
214220
gfs2_glock_dq_uninit(&ip->i_iopen_gh);
215221
if (gfs2_holder_initialized(&i_gh))

0 commit comments

Comments
 (0)