Commit e6c08367 authored by Tom Zanussi's avatar Tom Zanussi Committed by Linus Torvalds

[PATCH] relayfs: add support for global relay buffers

This patch adds the optional is_global outparam to the create_buf_file()
callback.  This can be used by clients to create a single global relayfs
buffer instead of the default per-cpu buffers.  This was suggested as being
useful for certain debugging applications where it's more convenient to be
able to get all the data from a single channel without having to go to the
bother of dealing with per-cpu files.
Signed-off-by: default avatarTom Zanussi <zanussi@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 03d78d11
...@@ -86,7 +86,8 @@ static void buf_unmapped_default_callback(struct rchan_buf *buf, ...@@ -86,7 +86,8 @@ static void buf_unmapped_default_callback(struct rchan_buf *buf,
static struct dentry *create_buf_file_default_callback(const char *filename, static struct dentry *create_buf_file_default_callback(const char *filename,
struct dentry *parent, struct dentry *parent,
int mode, int mode,
struct rchan_buf *buf) struct rchan_buf *buf,
int *is_global)
{ {
return relayfs_create_file(filename, parent, mode, return relayfs_create_file(filename, parent, mode,
&relayfs_file_operations, buf); &relayfs_file_operations, buf);
...@@ -170,14 +171,16 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init) ...@@ -170,14 +171,16 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
void relay_reset(struct rchan *chan) void relay_reset(struct rchan *chan)
{ {
unsigned int i; unsigned int i;
struct rchan_buf *prev = NULL;
if (!chan) if (!chan)
return; return;
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
if (!chan->buf[i]) if (!chan->buf[i] || chan->buf[i] == prev)
continue; break;
__relay_reset(chan->buf[i], 0); __relay_reset(chan->buf[i], 0);
prev = chan->buf[i];
} }
} }
...@@ -188,18 +191,22 @@ void relay_reset(struct rchan *chan) ...@@ -188,18 +191,22 @@ void relay_reset(struct rchan *chan)
*/ */
static struct rchan_buf *relay_open_buf(struct rchan *chan, static struct rchan_buf *relay_open_buf(struct rchan *chan,
const char *filename, const char *filename,
struct dentry *parent) struct dentry *parent,
int *is_global)
{ {
struct rchan_buf *buf; struct rchan_buf *buf;
struct dentry *dentry; struct dentry *dentry;
if (*is_global)
return chan->buf[0];
buf = relay_create_buf(chan); buf = relay_create_buf(chan);
if (!buf) if (!buf)
return NULL; return NULL;
/* Create file in fs */ /* Create file in fs */
dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR, dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR,
buf); buf, is_global);
if (!dentry) { if (!dentry) {
relay_destroy_buf(buf); relay_destroy_buf(buf);
return NULL; return NULL;
...@@ -273,6 +280,7 @@ struct rchan *relay_open(const char *base_filename, ...@@ -273,6 +280,7 @@ struct rchan *relay_open(const char *base_filename,
unsigned int i; unsigned int i;
struct rchan *chan; struct rchan *chan;
char *tmpname; char *tmpname;
int is_global = 0;
if (!base_filename) if (!base_filename)
return NULL; return NULL;
...@@ -297,7 +305,8 @@ struct rchan *relay_open(const char *base_filename, ...@@ -297,7 +305,8 @@ struct rchan *relay_open(const char *base_filename,
for_each_online_cpu(i) { for_each_online_cpu(i) {
sprintf(tmpname, "%s%d", base_filename, i); sprintf(tmpname, "%s%d", base_filename, i);
chan->buf[i] = relay_open_buf(chan, tmpname, parent); chan->buf[i] = relay_open_buf(chan, tmpname, parent,
&is_global);
chan->buf[i]->cpu = i; chan->buf[i]->cpu = i;
if (!chan->buf[i]) if (!chan->buf[i])
goto free_bufs; goto free_bufs;
...@@ -311,6 +320,8 @@ free_bufs: ...@@ -311,6 +320,8 @@ free_bufs:
if (!chan->buf[i]) if (!chan->buf[i])
break; break;
relay_close_buf(chan->buf[i]); relay_close_buf(chan->buf[i]);
if (is_global)
break;
} }
kfree(tmpname); kfree(tmpname);
...@@ -420,14 +431,16 @@ void relay_destroy_channel(struct kref *kref) ...@@ -420,14 +431,16 @@ void relay_destroy_channel(struct kref *kref)
void relay_close(struct rchan *chan) void relay_close(struct rchan *chan)
{ {
unsigned int i; unsigned int i;
struct rchan_buf *prev = NULL;
if (!chan) if (!chan)
return; return;
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
if (!chan->buf[i]) if (!chan->buf[i] || chan->buf[i] == prev)
continue; break;
relay_close_buf(chan->buf[i]); relay_close_buf(chan->buf[i]);
prev = chan->buf[i];
} }
if (chan->last_toobig) if (chan->last_toobig)
...@@ -447,14 +460,16 @@ void relay_close(struct rchan *chan) ...@@ -447,14 +460,16 @@ void relay_close(struct rchan *chan)
void relay_flush(struct rchan *chan) void relay_flush(struct rchan *chan)
{ {
unsigned int i; unsigned int i;
struct rchan_buf *prev = NULL;
if (!chan) if (!chan)
return; return;
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++) {
if (!chan->buf[i]) if (!chan->buf[i] || chan->buf[i] == prev)
continue; break;
relay_switch_subbuf(chan->buf[i], 0); relay_switch_subbuf(chan->buf[i], 0);
prev = chan->buf[i];
} }
} }
......
...@@ -116,6 +116,7 @@ struct rchan_callbacks ...@@ -116,6 +116,7 @@ struct rchan_callbacks
* @parent: the parent of the file to create * @parent: the parent of the file to create
* @mode: the mode of the file to create * @mode: the mode of the file to create
* @buf: the channel buffer * @buf: the channel buffer
* @is_global: outparam - set non-zero if the buffer should be global
* *
* Called during relay_open(), once for each per-cpu buffer, * Called during relay_open(), once for each per-cpu buffer,
* to allow the client to create a file to be used to * to allow the client to create a file to be used to
...@@ -126,12 +127,17 @@ struct rchan_callbacks ...@@ -126,12 +127,17 @@ struct rchan_callbacks
* The callback should return the dentry of the file created * The callback should return the dentry of the file created
* to represent the relay buffer. * to represent the relay buffer.
* *
* Setting the is_global outparam to a non-zero value will
* cause relay_open() to create a single global buffer rather
* than the default set of per-cpu buffers.
*
* See Documentation/filesystems/relayfs.txt for more info. * See Documentation/filesystems/relayfs.txt for more info.
*/ */
struct dentry *(*create_buf_file)(const char *filename, struct dentry *(*create_buf_file)(const char *filename,
struct dentry *parent, struct dentry *parent,
int mode, int mode,
struct rchan_buf *buf); struct rchan_buf *buf,
int *is_global);
/* /*
* remove_buf_file - remove file representing a relayfs channel buffer * remove_buf_file - remove file representing a relayfs channel buffer
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment