Commit ddf25aea authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Greg Kroah-Hartman

gfs2: Fix debugfs glocks dump

commit 10201655 upstream.

The switch to rhashtables (commit 88ffbf3e) broke the debugfs glock
dump (/sys/kernel/debug/gfs2/<device>/glocks) for dumps bigger than a
single buffer: the right function for restarting an rhashtable iteration
from the beginning of the hash table is rhashtable_walk_enter;
rhashtable_walk_stop + rhashtable_walk_start will just resume from the
current position.

The upstream commit doesn't directly apply to 4.4.y because 4.4.y
doesn't have rhashtable_walk_enter and the following mainline commits:

  92ecd73a  
    gfs2: Deduplicate gfs2_{glocks,glstats}_open
  cc37a627  
    gfs2: Replace rhashtable_walk_init with rhashtable_walk_enter

Other than rhashtable_walk_enter, rhashtable_walk_init can fail.  To
handle the failure case in gfs2_glock_seq_stop, we check if
rhashtable_walk_init has initialized iter->walker; if it has not, we
must not call rhashtable_walk_stop or rhashtable_walk_exit.
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d25fea06
...@@ -1814,13 +1814,10 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) ...@@ -1814,13 +1814,10 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
{ {
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
loff_t n = *pos; loff_t n = *pos;
int ret;
if (gi->last_pos <= *pos)
n = (*pos - gi->last_pos);
ret = rhashtable_walk_start(&gi->hti); if (rhashtable_walk_init(&gl_hash_table, &gi->hti) != 0)
if (ret) return NULL;
if (rhashtable_walk_start(&gi->hti) != 0)
return NULL; return NULL;
do { do {
...@@ -1828,6 +1825,7 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos) ...@@ -1828,6 +1825,7 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
} while (gi->gl && n--); } while (gi->gl && n--);
gi->last_pos = *pos; gi->last_pos = *pos;
return gi->gl; return gi->gl;
} }
...@@ -1839,6 +1837,7 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr, ...@@ -1839,6 +1837,7 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
(*pos)++; (*pos)++;
gi->last_pos = *pos; gi->last_pos = *pos;
gfs2_glock_iter_next(gi); gfs2_glock_iter_next(gi);
return gi->gl; return gi->gl;
} }
...@@ -1847,7 +1846,10 @@ static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr) ...@@ -1847,7 +1846,10 @@ static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
gi->gl = NULL; gi->gl = NULL;
rhashtable_walk_stop(&gi->hti); if (gi->hti.walker) {
rhashtable_walk_stop(&gi->hti);
rhashtable_walk_exit(&gi->hti);
}
} }
static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr) static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
...@@ -1910,12 +1912,10 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file) ...@@ -1910,12 +1912,10 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file)
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
gi->sdp = inode->i_private; gi->sdp = inode->i_private;
gi->last_pos = 0;
seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN); seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
if (seq->buf) if (seq->buf)
seq->size = GFS2_SEQ_GOODSIZE; seq->size = GFS2_SEQ_GOODSIZE;
gi->gl = NULL; gi->gl = NULL;
ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
} }
return ret; return ret;
} }
...@@ -1926,7 +1926,6 @@ static int gfs2_glocks_release(struct inode *inode, struct file *file) ...@@ -1926,7 +1926,6 @@ static int gfs2_glocks_release(struct inode *inode, struct file *file)
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
gi->gl = NULL; gi->gl = NULL;
rhashtable_walk_exit(&gi->hti);
return seq_release_private(inode, file); return seq_release_private(inode, file);
} }
...@@ -1938,12 +1937,10 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file) ...@@ -1938,12 +1937,10 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file)
struct seq_file *seq = file->private_data; struct seq_file *seq = file->private_data;
struct gfs2_glock_iter *gi = seq->private; struct gfs2_glock_iter *gi = seq->private;
gi->sdp = inode->i_private; gi->sdp = inode->i_private;
gi->last_pos = 0;
seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN); seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
if (seq->buf) if (seq->buf)
seq->size = GFS2_SEQ_GOODSIZE; seq->size = GFS2_SEQ_GOODSIZE;
gi->gl = NULL; gi->gl = NULL;
ret = rhashtable_walk_init(&gl_hash_table, &gi->hti);
} }
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment