From: Shiju Jose <[email protected]> When userspace reads a trace event format file, the maximum data size that can be read is limited to PAGE_SIZE by the seq_read() and seq_read_iter() functions. This results in userspace receiving partial data if the format file is larger than PAGE_SIZE, requiring a workaround to read the complete data from the format file.
Add support for reading trace event format files larger than PAGE_SIZE when needed by userspace. Signed-off-by: Shiju Jose <[email protected]> --- kernel/trace/trace_events.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 1545cc8b49d0..ef33614e7f22 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1801,6 +1801,36 @@ static int trace_format_open(struct inode *inode, struct file *file) return 0; } +/** + * trace_format_read - read() method for format file. + * @file: the file to read from + * @buf: the buffer to read to + * @size: the maximum number of bytes to read + * @ppos: the current position in the file + * + * * Return: + * * %0 - No bytes copied (EOF). + * * %>0 - Number of bytes copied. + * * %<0 - Error code. + */ +static ssize_t trace_format_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) +{ + ssize_t copied = 0; + ssize_t ret; + + do { + ret = seq_read(file, buf + copied, size - copied, ppos); + if (ret < 0) + return ret; + + copied += ret; + if (copied >= size) + break; + } while (ret); + + return copied; +} + #ifdef CONFIG_PERF_EVENTS static ssize_t event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) @@ -2284,7 +2314,7 @@ static const struct file_operations ftrace_enable_fops = { static const struct file_operations ftrace_event_format_fops = { .open = trace_format_open, - .read = seq_read, + .read = trace_format_read, .llseek = seq_lseek, .release = seq_release, }; -- 2.43.0
