When several instances enable copy_trace_marker, stopping one instance can prevent the remaining buffers from receiving markers. Continue copying text and raw markers even if one copy fails, and return the last error after trying all buffers. Fixes: 7b382efd5e8a ("tracing: Allow the top level trace_marker to write into another instances") Cc: stable@vger.kernel.org Signed-off-by: Jaewon Jung --- The current code stops at the first error without trying the remaining buffers. This patch tries all buffers even if a write fails, and returns the last error. Returning either the first or last error cannot report all failures. I chose the last error to keep the code simple. Per-buffer error reporting is outside the scope of this patch. Please let me know if you prefer a different error return policy. Tested on x86_64 QEMU: - Setup: Enable copy_trace_marker in multiple instances and set tracing_on=0 in one instance before a live buffer in the copy order. - Before: No markers in live buffers after the stopped instance; write() returns an error. - After: Markers in all live buffers; write() returns an error. - Existing text/raw marker and instance selftests: 6 PASS. kernel/trace/trace.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index e8c4efa8107b..bddcb35835be 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -6316,6 +6316,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, { struct trace_array *tr = filp->private_data; ssize_t written = -ENODEV; + ssize_t error = 0; unsigned long ip; char *buf; @@ -6346,14 +6347,13 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, guard(rcu)(); list_for_each_entry_rcu(tr, &marker_copies, marker_list) { written = write_marker_to_buffer(tr, buf, cnt, ip); - if (written < 0) - break; + error = written < 0 ? written : error; } } else { written = write_marker_to_buffer(tr, buf, cnt, ip); } - return written; + return error ? error : written; } static ssize_t write_raw_marker_to_buffer(struct trace_array *tr, @@ -6397,6 +6397,7 @@ tracing_mark_raw_write(struct file *filp, const char __user *ubuf, { struct trace_array *tr = filp->private_data; ssize_t written = -ENODEV; + ssize_t error = 0; char *buf; if (unlikely(tracing_disabled)) @@ -6425,14 +6426,13 @@ tracing_mark_raw_write(struct file *filp, const char __user *ubuf, guard(rcu)(); list_for_each_entry_rcu(tr, &marker_copies, marker_list) { written = write_raw_marker_to_buffer(tr, buf, cnt); - if (written < 0) - break; + error = written < 0 ? written : error; } } else { written = write_raw_marker_to_buffer(tr, buf, cnt); } - return written; + return error ? error : written; } static int tracing_mark_open(struct inode *inode, struct file *filp) base-commit: c339f4010dea8b0d754f84ace70cd1b089878ef8 -- 2.43.0