To make seq_buf more lightweight as a string buf, move the readpos member
from seq_buf to its container, trace_seq.  That puts the responsibility
of maintaining the readpos entirely in the tracing code.  If some future
users want to package up the readpos with a seq_buf, we can define a
new struct then.

Signed-off-by: Matthew Wilcox (Oracle) <wi...@infradead.org>
---
 include/linux/seq_buf.h   |  5 +----
 include/linux/trace_seq.h |  2 ++
 kernel/trace/trace.c      | 10 +++++-----
 kernel/trace/trace_seq.c  |  6 +++++-
 lib/seq_buf.c             | 13 +++++--------
 5 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/include/linux/seq_buf.h b/include/linux/seq_buf.h
index 515d7fcb9634..a0fb013cebdf 100644
--- a/include/linux/seq_buf.h
+++ b/include/linux/seq_buf.h
@@ -14,19 +14,16 @@
  * @buffer:    pointer to the buffer
  * @size:      size of the buffer
  * @len:       the amount of data inside the buffer
- * @readpos:   The next position to read in the buffer.
  */
 struct seq_buf {
        char                    *buffer;
        size_t                  size;
        size_t                  len;
-       loff_t                  readpos;
 };
 
 static inline void seq_buf_clear(struct seq_buf *s)
 {
        s->len = 0;
-       s->readpos = 0;
 }
 
 static inline void
@@ -143,7 +140,7 @@ extern __printf(2, 0)
 int seq_buf_vprintf(struct seq_buf *s, const char *fmt, va_list args);
 extern int seq_buf_print_seq(struct seq_file *m, struct seq_buf *s);
 extern int seq_buf_to_user(struct seq_buf *s, char __user *ubuf,
-                          int cnt);
+                          size_t start, int cnt);
 extern int seq_buf_puts(struct seq_buf *s, const char *str);
 extern int seq_buf_putc(struct seq_buf *s, unsigned char c);
 extern int seq_buf_putmem(struct seq_buf *s, const void *mem, unsigned int 
len);
diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h
index 6be92bf559fe..3691e0e76a1a 100644
--- a/include/linux/trace_seq.h
+++ b/include/linux/trace_seq.h
@@ -14,6 +14,7 @@
 struct trace_seq {
        char                    buffer[PAGE_SIZE];
        struct seq_buf          seq;
+       size_t                  readpos;
        int                     full;
 };
 
@@ -22,6 +23,7 @@ trace_seq_init(struct trace_seq *s)
 {
        seq_buf_init(&s->seq, s->buffer, PAGE_SIZE);
        s->full = 0;
+       s->readpos = 0;
 }
 
 /**
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index abaaf516fcae..217cabd09c3e 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1730,15 +1730,15 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, 
void *buf, size_t cnt)
 {
        int len;
 
-       if (trace_seq_used(s) <= s->seq.readpos)
+       if (trace_seq_used(s) <= s->readpos)
                return -EBUSY;
 
-       len = trace_seq_used(s) - s->seq.readpos;
+       len = trace_seq_used(s) - s->readpos;
        if (cnt > len)
                cnt = len;
-       memcpy(buf, s->buffer + s->seq.readpos, cnt);
+       memcpy(buf, s->buffer + s->readpos, cnt);
 
-       s->seq.readpos += cnt;
+       s->readpos += cnt;
        return cnt;
 }
 
@@ -7006,7 +7006,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf,
 
        /* Now copy what we have to the user */
        sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
-       if (iter->seq.seq.readpos >= trace_seq_used(&iter->seq))
+       if (iter->seq.readpos >= trace_seq_used(&iter->seq))
                trace_seq_init(&iter->seq);
 
        /*
diff --git a/kernel/trace/trace_seq.c b/kernel/trace/trace_seq.c
index bac06ee3b98b..7be97229ddf8 100644
--- a/kernel/trace/trace_seq.c
+++ b/kernel/trace/trace_seq.c
@@ -370,8 +370,12 @@ EXPORT_SYMBOL_GPL(trace_seq_path);
  */
 int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
 {
+       int ret;
        __trace_seq_init(s);
-       return seq_buf_to_user(&s->seq, ubuf, cnt);
+       ret = seq_buf_to_user(&s->seq, ubuf, s->readpos, cnt);
+       if (ret > 0)
+               s->readpos += ret;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(trace_seq_to_user);
 
diff --git a/lib/seq_buf.c b/lib/seq_buf.c
index 45c450f423fa..0d218f3835ae 100644
--- a/lib/seq_buf.c
+++ b/lib/seq_buf.c
@@ -340,7 +340,7 @@ int seq_buf_path(struct seq_buf *s, const struct path 
*path, const char *esc)
  *
  * Returns -EFAULT if the copy to userspace fails.
  */
-int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt)
+int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, size_t start, int 
cnt)
 {
        int len;
        int ret;
@@ -350,20 +350,17 @@ int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, 
int cnt)
 
        len = seq_buf_used(s);
 
-       if (len <= s->readpos)
+       if (len <= start)
                return -EBUSY;
 
-       len -= s->readpos;
+       len -= start;
        if (cnt > len)
                cnt = len;
-       ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
+       ret = copy_to_user(ubuf, s->buffer + start, cnt);
        if (ret == cnt)
                return -EFAULT;
 
-       cnt -= ret;
-
-       s->readpos += cnt;
-       return cnt;
+       return cnt - ret;
 }
 
 /**
-- 
2.40.1


Reply via email to