[PATCH] relayfs: add support for global relay buffers
authorTom Zanussi <zanussi@us.ibm.com>
Sun, 8 Jan 2006 09:02:29 +0000 (01:02 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 9 Jan 2006 04:13:50 +0000 (20:13 -0800)
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: Tom Zanussi <zanussi@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/relayfs/relay.c
include/linux/relayfs_fs.h

index b9bb569032729ec541124855a169d96589214eff..2935a6ab8ffab629d3d7d5f7cd312d567bb37941 100644 (file)
@@ -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,
                                                       struct dentry *parent,
                                                       int mode,
-                                                      struct rchan_buf *buf)
+                                                      struct rchan_buf *buf,
+                                                      int *is_global)
 {
        return relayfs_create_file(filename, parent, mode,
                                   &relayfs_file_operations, buf);
@@ -170,14 +171,16 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
 void relay_reset(struct rchan *chan)
 {
        unsigned int i;
+       struct rchan_buf *prev = NULL;
 
        if (!chan)
                return;
 
        for (i = 0; i < NR_CPUS; i++) {
-               if (!chan->buf[i])
-                       continue;
+               if (!chan->buf[i] || chan->buf[i] == prev)
+                       break;
                __relay_reset(chan->buf[i], 0);
+               prev = chan->buf[i];
        }
 }
 
@@ -188,18 +191,22 @@ void relay_reset(struct rchan *chan)
  */
 static struct rchan_buf *relay_open_buf(struct rchan *chan,
                                        const char *filename,
-                                       struct dentry *parent)
+                                       struct dentry *parent,
+                                       int *is_global)
 {
        struct rchan_buf *buf;
        struct dentry *dentry;
 
+       if (*is_global)
+               return chan->buf[0];
+
        buf = relay_create_buf(chan);
        if (!buf)
                return NULL;
 
        /* Create file in fs */
        dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR,
-                                          buf);
+                                          buf, is_global);
        if (!dentry) {
                relay_destroy_buf(buf);
                return NULL;
@@ -273,6 +280,7 @@ struct rchan *relay_open(const char *base_filename,
        unsigned int i;
        struct rchan *chan;
        char *tmpname;
+       int is_global = 0;
 
        if (!base_filename)
                return NULL;
@@ -297,7 +305,8 @@ struct rchan *relay_open(const char *base_filename,
 
        for_each_online_cpu(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;
                if (!chan->buf[i])
                        goto free_bufs;
@@ -311,6 +320,8 @@ free_bufs:
                if (!chan->buf[i])
                        break;
                relay_close_buf(chan->buf[i]);
+               if (is_global)
+                       break;
        }
        kfree(tmpname);
 
@@ -420,14 +431,16 @@ void relay_destroy_channel(struct kref *kref)
 void relay_close(struct rchan *chan)
 {
        unsigned int i;
+       struct rchan_buf *prev = NULL;
 
        if (!chan)
                return;
 
        for (i = 0; i < NR_CPUS; i++) {
-               if (!chan->buf[i])
-                       continue;
+               if (!chan->buf[i] || chan->buf[i] == prev)
+                       break;
                relay_close_buf(chan->buf[i]);
+               prev = chan->buf[i];
        }
 
        if (chan->last_toobig)
@@ -447,14 +460,16 @@ void relay_close(struct rchan *chan)
 void relay_flush(struct rchan *chan)
 {
        unsigned int i;
+       struct rchan_buf *prev = NULL;
 
        if (!chan)
                return;
 
        for (i = 0; i < NR_CPUS; i++) {
-               if (!chan->buf[i])
-                       continue;
+               if (!chan->buf[i] || chan->buf[i] == prev)
+                       break;
                relay_switch_subbuf(chan->buf[i], 0);
+               prev = chan->buf[i];
        }
 }
 
index 8c21771058571ffa29053250411f168812670a51..30f45511b40dde02bb78ad01dcba4f21280cf5a1 100644 (file)
@@ -116,6 +116,7 @@ struct rchan_callbacks
         * @parent: the parent of the file to create
         * @mode: the mode of the file to create
         * @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,
         * to allow the client to create a file to be used to
@@ -126,12 +127,17 @@ struct rchan_callbacks
         * The callback should return the dentry of the file created
         * 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.
         */
        struct dentry *(*create_buf_file)(const char *filename,
                                          struct dentry *parent,
                                          int mode,
-                                         struct rchan_buf *buf);
+                                         struct rchan_buf *buf,
+                                         int *is_global);
 
        /*
         * remove_buf_file - remove file representing a relayfs channel buffer