[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250512024935.64704-2-kerneljasonxing@gmail.com>
Date: Mon, 12 May 2025 10:49:31 +0800
From: Jason Xing <kerneljasonxing@...il.com>
To: axboe@...nel.dk,
rostedt@...dmis.org,
mhiramat@...nel.org,
mathieu.desnoyers@...icios.com,
akpm@...ux-foundation.org
Cc: linux-kernel@...r.kernel.org,
linux-block@...r.kernel.org,
linux-trace-kernel@...r.kernel.org,
Jason Xing <kernelxing@...cent.com>,
Yushan Zhou <katrinzhou@...cent.com>
Subject: [PATCH v1 1/5] relayfs: support a counter tracking if per-cpu buffers is full
From: Jason Xing <kernelxing@...cent.com>
Add 'full' field in per-cpu buffer structure to detect if the buffer is
full, which means: 1) relayfs doesn't intend to accept new data in
non-overwrite mode that is also by default, or 2) relayfs is going to
start over again and overwrite old unread data when kernel module has
its own subbuf_start callback to support overwrite mode. This counter
works for both overwrite and non-overwrite modes.
This counter doesn't have any explicit lock to protect from being
modified by different threads at the same time for the better
performance consideration. In terms of the atomic operation, it's not
introduced for incrementing the counter like blktrace because side
effect may arise when multiple threads access the counter simultaneously
on the machine equipped with many cpus, say, more than 200. As we can
see in relay_write() and __relay_write(), the writer at the beginning
should consider how to use the lock for the whole write process, thus
it's not necessary to add another lock to make sure the counter is
accurate.
Using 'pahole --hex -C rchan_buf vmlinux' so you can see this field just
fits into one 4-byte hole in the cacheline 2.
Reviewed-by: Yushan Zhou <katrinzhou@...cent.com>
Signed-off-by: Jason Xing <kernelxing@...cent.com>
---
include/linux/relay.h | 9 +++++++++
kernel/relay.c | 8 +++++++-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/include/linux/relay.h b/include/linux/relay.h
index f80b0eb1e905..022cf11e5a92 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -28,6 +28,14 @@
*/
#define RELAYFS_CHANNEL_VERSION 7
+/*
+ * Relay buffer error statistics dump
+ */
+struct rchan_buf_error_stats
+{
+ unsigned int full; /* counter for buffer full */
+};
+
/*
* Per-cpu relay channel buffer
*/
@@ -43,6 +51,7 @@ struct rchan_buf
struct irq_work wakeup_work; /* reader wakeup */
struct dentry *dentry; /* channel file dentry */
struct kref kref; /* channel buffer refcount */
+ struct rchan_buf_error_stats stats; /* error stats */
struct page **page_array; /* array of current buffer pages */
unsigned int page_count; /* number of current buffer pages */
unsigned int finalized; /* buffer has been finalized */
diff --git a/kernel/relay.c b/kernel/relay.c
index 5aeb9226e238..b5db4aa60da1 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -252,8 +252,13 @@ EXPORT_SYMBOL_GPL(relay_buf_full);
static int relay_subbuf_start(struct rchan_buf *buf, void *subbuf,
void *prev_subbuf)
{
+ int buf_full = relay_buf_full(buf);
+
+ if (buf_full)
+ buf->stats.full++;
+
if (!buf->chan->cb->subbuf_start)
- return !relay_buf_full(buf);
+ return !buf_full;
return buf->chan->cb->subbuf_start(buf, subbuf,
prev_subbuf);
@@ -298,6 +303,7 @@ static void __relay_reset(struct rchan_buf *buf, unsigned int init)
buf->finalized = 0;
buf->data = buf->start;
buf->offset = 0;
+ buf->stats.full = 0;
for (i = 0; i < buf->chan->n_subbufs; i++)
buf->padding[i] = 0;
--
2.43.5
Powered by blists - more mailing lists