Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62f0b3eb authored by Steven Rostedt's avatar Steven Rostedt Committed by Steven Rostedt
Browse files

ring-buffer: check for swapped buffers in start of committing



Because the irqsoff tracer can swap an internal CPU buffer, it is possible
that a swap happens between the start of the write and before the committing
bit is set (the committing bit will disable swapping).

This patch adds a check for this and will fail the write if it detects it.

Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent e8165dbb
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -2073,7 +2073,8 @@ static void rb_end_commit(struct ring_buffer_per_cpu *cpu_buffer)
}

static struct ring_buffer_event *
rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer,
rb_reserve_next_event(struct ring_buffer *buffer,
		      struct ring_buffer_per_cpu *cpu_buffer,
		      unsigned long length)
{
	struct ring_buffer_event *event;
@@ -2083,6 +2084,19 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer,

	rb_start_commit(cpu_buffer);

	/*
	 * Due to the ability to swap a cpu buffer from a buffer
	 * it is possible it was swapped before we committed.
	 * (committing stops a swap). We check for it here and
	 * if it happened, we have to fail the write.
	 */
	barrier();
	if (unlikely(ACCESS_ONCE(cpu_buffer->buffer) != buffer)) {
		local_dec(&cpu_buffer->committing);
		local_dec(&cpu_buffer->commits);
		return NULL;
	}

	length = rb_calculate_event_length(length);
 again:
	/*
@@ -2243,7 +2257,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, unsigned long length)
	if (length > BUF_MAX_DATA_SIZE)
		goto out;

	event = rb_reserve_next_event(cpu_buffer, length);
	event = rb_reserve_next_event(buffer, cpu_buffer, length);
	if (!event)
		goto out;

@@ -2476,7 +2490,7 @@ int ring_buffer_write(struct ring_buffer *buffer,
	if (length > BUF_MAX_DATA_SIZE)
		goto out;

	event = rb_reserve_next_event(cpu_buffer, length);
	event = rb_reserve_next_event(buffer, cpu_buffer, length);
	if (!event)
		goto out;