tracing: Move readpos from seq_buf to trace_seq
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 20 Oct 2023 03:35:45 +0000 (04:35 +0100)
committerSteven Rostedt (Google) <rostedt@goodmis.org>
Fri, 20 Oct 2023 16:16:10 +0000 (12:16 -0400)
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.

Link: https://lore.kernel.org/linux-trace-kernel/20231020033545.2587554-2-willy@infradead.org
Cc: Kees Cook <keescook@chromium.org>
Cc: Justin Stitt <justinstitt@google.com>
Cc: Kent Overstreet <kent.overstreet@linux.dev>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
include/linux/seq_buf.h
include/linux/trace_seq.h
kernel/trace/trace.c
kernel/trace/trace_seq.c
lib/seq_buf.c

index 515d7fcb9634b556c7b9a77b0757900c3aa1a3ea..a0fb013cebdf22222314afcd4bfdf8f70d217e13 100644 (file)
  * @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);
index 6be92bf559fe7c17839ab3f1979cc34b20235741..3691e0e76a1a209601f97fe03ca97738dafcd841 100644 (file)
@@ -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;
 }
 
 /**
index 4383be8fa1b0f74eb72d63f9c222b705e5b9a71e..d629065c238357983120256dc45b11392d1b5c97 100644 (file)
@@ -1731,15 +1731,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;
 }
 
@@ -7008,7 +7008,7 @@ waitagain:
 
        /* 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);
 
        /*
index bac06ee3b98b8124d77e35a8f385a6fad61b0707..7be97229ddf86008a4fa91c4872f3b9eb85a5181 100644 (file)
@@ -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);
 
index 45c450f423fa87aca55bc8c4a9e9f0629c8e708b..b7477aefff537c5c558c7c52afac37fd0c68ee2d 100644 (file)
@@ -324,23 +324,24 @@ int seq_buf_path(struct seq_buf *s, const struct path *path, const char *esc)
  * seq_buf_to_user - copy the sequence buffer to user space
  * @s: seq_buf descriptor
  * @ubuf: The userspace memory location to copy to
+ * @start: The first byte in the buffer to copy
  * @cnt: The amount to copy
  *
  * Copies the sequence buffer into the userspace memory pointed to
- * by @ubuf. It starts from the last read position (@s->readpos)
- * and writes up to @cnt characters or till it reaches the end of
- * the content in the buffer (@s->len), which ever comes first.
+ * by @ubuf. It starts from @start and writes up to @cnt characters
+ * or until it reaches the end of the content in the buffer (@s->len),
+ * whichever comes first.
  *
  * On success, it returns a positive number of the number of bytes
  * it copied.
  *
  * On failure it returns -EBUSY if all of the content in the
  * sequence has been already read, which includes nothing in the
- * sequence (@s->len == @s->readpos).
+ * sequence (@s->len == @start).
  *
  * 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 +351,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;
 }
 
 /**