[Cluster-devel] [PATCH 1/3] gfs2: Glock dump improvement (1)
Andreas Gruenbacher
agruenba at redhat.com
Mon Dec 18 13:31:20 UTC 2017
Restore an optimization removed in commit 10201655b0 "Fix debugfs glocks
dump": keep the glock hash table iterator active while the glock dump
file is held open. This avoids having to rescan the hash table from the
start if the user-space buffer the kernel is writing to is sufficiently
small.
This is a partial fix only: if the user-space buffer is roughly as big
as the kernel buffer, the kernel will eventually end up at an entry that
exceeds the kernel-internal buffer (gfs2_glock_seq_show). The output up
to but excluding that entry will be copied to user-space. Upon the next
sequential read from user-space, gfs2_glock_seq_start will seek to that
partial entry at the current position, and will continue from there. At
the moment, this requires scanning the hash table from the start.
Signed-off-by: Andreas Gruenbacher <agruenba at redhat.com>
---
fs/gfs2/glock.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 11066d8647d2..93c7cd2325b4 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -1944,18 +1944,29 @@ static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(RCU)
{
struct gfs2_glock_iter *gi = seq->private;
- loff_t n = *pos;
+ loff_t n;
+
+ /*
+ * From the current position, we can either skip to the next hash table
+ * entry or start from the beginning.
+ */
+ if (*pos <= gi->last_pos) {
+ rhashtable_walk_exit(&gi->hti);
+ rhashtable_walk_enter(&gl_hash_table, &gi->hti);
+ n = *pos + 1;
+ } else
+ n = *pos - gi->last_pos;
- rhashtable_walk_enter(&gl_hash_table, &gi->hti);
if (rhashtable_walk_start(&gi->hti) != 0)
return NULL;
- do {
+ while (n--) {
gfs2_glock_iter_next(gi);
- } while (gi->gl && n--);
+ if (!gi->gl)
+ break;
+ }
gi->last_pos = *pos;
-
return gi->gl;
}
@@ -1967,7 +1978,6 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
(*pos)++;
gi->last_pos = *pos;
gfs2_glock_iter_next(gi);
-
return gi->gl;
}
@@ -1978,7 +1988,6 @@ static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)
gi->gl = NULL;
rhashtable_walk_stop(&gi->hti);
- rhashtable_walk_exit(&gi->hti);
}
static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
@@ -2041,10 +2050,16 @@ static int __gfs2_glocks_open(struct inode *inode, struct file *file,
struct gfs2_glock_iter *gi = seq->private;
gi->sdp = inode->i_private;
+ /*
+ * Initially, we are "before" the first hash table entry; the
+ * first call to rhashtable_walk_next gets us the first entry.
+ */
+ gi->last_pos = -1;
seq->buf = kmalloc(GFS2_SEQ_GOODSIZE, GFP_KERNEL | __GFP_NOWARN);
if (seq->buf)
seq->size = GFS2_SEQ_GOODSIZE;
gi->gl = NULL;
+ rhashtable_walk_enter(&gl_hash_table, &gi->hti);
}
return ret;
}
@@ -2060,6 +2075,7 @@ static int gfs2_glocks_release(struct inode *inode, struct file *file)
struct gfs2_glock_iter *gi = seq->private;
gi->gl = NULL;
+ rhashtable_walk_exit(&gi->hti);
return seq_release_private(inode, file);
}
--
2.14.3
More information about the Cluster-devel
mailing list