Skip to content

Commit 7427f3b

Browse files
author
Andreas Gruenbacher
committed
gfs2: Fix glock_hash_walk bugs
So far, glock_hash_walk took a reference on each glock it iterated over, and it was the examiner's responsibility to drop those references. Dropping the final reference to a glock can sleep and the examiners are called in a RCU critical section with spin locks held, so examiners that didn't need the extra reference had to drop it asynchronously via gfs2_glock_queue_put or similar. This wasn't done correctly in thaw_glock which did call gfs2_glock_put, and not at all in dump_glock_func. Change glock_hash_walk to not take glock references at all. That way, the examiners that don't need them won't have to bother with slow asynchronous puts, and the examiners that do need references can take them themselves. Reported-by: Alexander Aring <aahringo@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
1 parent 486408d commit 7427f3b

1 file changed

Lines changed: 12 additions & 10 deletions

File tree

fs/gfs2/glock.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,10 +2101,10 @@ static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
21012101
do {
21022102
rhashtable_walk_start(&iter);
21032103

2104-
while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl))
2105-
if (gl->gl_name.ln_sbd == sdp &&
2106-
lockref_get_not_dead(&gl->gl_lockref))
2104+
while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl)) {
2105+
if (gl->gl_name.ln_sbd == sdp)
21072106
examiner(gl);
2107+
}
21082108

21092109
rhashtable_walk_stop(&iter);
21102110
} while (cond_resched(), gl == ERR_PTR(-EAGAIN));
@@ -2146,7 +2146,6 @@ static void flush_delete_work(struct gfs2_glock *gl)
21462146
&gl->gl_delete, 0);
21472147
}
21482148
}
2149-
gfs2_glock_queue_work(gl, 0);
21502149
}
21512150

21522151
void gfs2_flush_delete_work(struct gfs2_sbd *sdp)
@@ -2163,10 +2162,10 @@ void gfs2_flush_delete_work(struct gfs2_sbd *sdp)
21632162

21642163
static void thaw_glock(struct gfs2_glock *gl)
21652164
{
2166-
if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) {
2167-
gfs2_glock_put(gl);
2165+
if (!test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))
2166+
return;
2167+
if (!lockref_get_not_dead(&gl->gl_lockref))
21682168
return;
2169-
}
21702169
set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
21712170
gfs2_glock_queue_work(gl, 0);
21722171
}
@@ -2182,9 +2181,12 @@ static void clear_glock(struct gfs2_glock *gl)
21822181
gfs2_glock_remove_from_lru(gl);
21832182

21842183
spin_lock(&gl->gl_lockref.lock);
2185-
if (gl->gl_state != LM_ST_UNLOCKED)
2186-
handle_callback(gl, LM_ST_UNLOCKED, 0, false);
2187-
__gfs2_glock_queue_work(gl, 0);
2184+
if (!__lockref_is_dead(&gl->gl_lockref)) {
2185+
gl->gl_lockref.count++;
2186+
if (gl->gl_state != LM_ST_UNLOCKED)
2187+
handle_callback(gl, LM_ST_UNLOCKED, 0, false);
2188+
__gfs2_glock_queue_work(gl, 0);
2189+
}
21882190
spin_unlock(&gl->gl_lockref.lock);
21892191
}
21902192

0 commit comments

Comments
 (0)