Skip to content

Commit

Permalink
gfs2: Use rhashtable walk interface in glock_hash_walk
Browse files Browse the repository at this point in the history
The function glock_hash_walk walks the rhashtable by hand.  This
is broken because if it catches the hash table in the middle of
a rehash, then it will miss entries.

This patch replaces the manual walk by using the rhashtable walk
interface.

Fixes: 88ffbf3 ("GFS2: Use resizable hash table for glocks")
Signed-off-by: Herbert Xu <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
herbertx authored and davem330 committed Feb 14, 2017
1 parent 4872e57 commit 6a25478
Showing 1 changed file with 17 additions and 11 deletions.
28 changes: 17 additions & 11 deletions fs/gfs2/glock.c
Original file line number Diff line number Diff line change
Expand Up @@ -1420,26 +1420,32 @@ static struct shrinker glock_shrinker = {
* @sdp: the filesystem
* @bucket: the bucket
*
* Note that the function can be called multiple times on the same
* object. So the user must ensure that the function can cope with
* that.
*/

static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
{
struct gfs2_glock *gl;
struct rhash_head *pos;
const struct bucket_table *tbl;
int i;
struct rhashtable_iter iter;

rcu_read_lock();
tbl = rht_dereference_rcu(gl_hash_table.tbl, &gl_hash_table);
for (i = 0; i < tbl->size; i++) {
rht_for_each_entry_rcu(gl, pos, tbl, i, gl_node) {
rhashtable_walk_enter(&gl_hash_table, &iter);

do {
gl = ERR_PTR(rhashtable_walk_start(&iter));
if (gl)
continue;

while ((gl = rhashtable_walk_next(&iter)) && !IS_ERR(gl))
if ((gl->gl_name.ln_sbd == sdp) &&
lockref_get_not_dead(&gl->gl_lockref))
examiner(gl);
}
}
rcu_read_unlock();
cond_resched();

rhashtable_walk_stop(&iter);
} while (cond_resched(), gl == ERR_PTR(-EAGAIN));

rhashtable_walk_exit(&iter);
}

/**
Expand Down

0 comments on commit 6a25478

Please sign in to comment.