aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/relayfs/relay.c35
-rw-r--r--include/linux/relayfs_fs.h8
2 files changed, 32 insertions, 11 deletions
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
index b9bb56903272..2935a6ab8ffa 100644
--- a/fs/relayfs/relay.c
+++ b/fs/relayfs/relay.c
@@ -86,7 +86,8 @@ static void buf_unmapped_default_callback(struct rchan_buf *buf,
86static struct dentry *create_buf_file_default_callback(const char *filename, 86static struct dentry *create_buf_file_default_callback(const char *filename,
87 struct dentry *parent, 87 struct dentry *parent,
88 int mode, 88 int mode,
89 struct rchan_buf *buf) 89 struct rchan_buf *buf,
90 int *is_global)
90{ 91{
91 return relayfs_create_file(filename, parent, mode, 92 return relayfs_create_file(filename, parent, mode,
92 &relayfs_file_operations, buf); 93 &relayfs_file_operations, buf);
@@ -170,14 +171,16 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
170void relay_reset(struct rchan *chan) 171void relay_reset(struct rchan *chan)
171{ 172{
172 unsigned int i; 173 unsigned int i;
174 struct rchan_buf *prev = NULL;
173 175
174 if (!chan) 176 if (!chan)
175 return; 177 return;
176 178
177 for (i = 0; i < NR_CPUS; i++) { 179 for (i = 0; i < NR_CPUS; i++) {
178 if (!chan->buf[i]) 180 if (!chan->buf[i] || chan->buf[i] == prev)
179 continue; 181 break;
180 __relay_reset(chan->buf[i], 0); 182 __relay_reset(chan->buf[i], 0);
183 prev = chan->buf[i];
181 } 184 }
182} 185}
183 186
@@ -188,18 +191,22 @@ void relay_reset(struct rchan *chan)
188 */ 191 */
189static struct rchan_buf *relay_open_buf(struct rchan *chan, 192static struct rchan_buf *relay_open_buf(struct rchan *chan,
190 const char *filename, 193 const char *filename,
191 struct dentry *parent) 194 struct dentry *parent,
195 int *is_global)
192{ 196{
193 struct rchan_buf *buf; 197 struct rchan_buf *buf;
194 struct dentry *dentry; 198 struct dentry *dentry;
195 199
200 if (*is_global)
201 return chan->buf[0];
202
196 buf = relay_create_buf(chan); 203 buf = relay_create_buf(chan);
197 if (!buf) 204 if (!buf)
198 return NULL; 205 return NULL;
199 206
200 /* Create file in fs */ 207 /* Create file in fs */
201 dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR, 208 dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR,
202 buf); 209 buf, is_global);
203 if (!dentry) { 210 if (!dentry) {
204 relay_destroy_buf(buf); 211 relay_destroy_buf(buf);
205 return NULL; 212 return NULL;
@@ -273,6 +280,7 @@ struct rchan *relay_open(const char *base_filename,
273 unsigned int i; 280 unsigned int i;
274 struct rchan *chan; 281 struct rchan *chan;
275 char *tmpname; 282 char *tmpname;
283 int is_global = 0;
276 284
277 if (!base_filename) 285 if (!base_filename)
278 return NULL; 286 return NULL;
@@ -297,7 +305,8 @@ struct rchan *relay_open(const char *base_filename,
297 305
298 for_each_online_cpu(i) { 306 for_each_online_cpu(i) {
299 sprintf(tmpname, "%s%d", base_filename, i); 307 sprintf(tmpname, "%s%d", base_filename, i);
300 chan->buf[i] = relay_open_buf(chan, tmpname, parent); 308 chan->buf[i] = relay_open_buf(chan, tmpname, parent,
309 &is_global);
301 chan->buf[i]->cpu = i; 310 chan->buf[i]->cpu = i;
302 if (!chan->buf[i]) 311 if (!chan->buf[i])
303 goto free_bufs; 312 goto free_bufs;
@@ -311,6 +320,8 @@ free_bufs:
311 if (!chan->buf[i]) 320 if (!chan->buf[i])
312 break; 321 break;
313 relay_close_buf(chan->buf[i]); 322 relay_close_buf(chan->buf[i]);
323 if (is_global)
324 break;
314 } 325 }
315 kfree(tmpname); 326 kfree(tmpname);
316 327
@@ -420,14 +431,16 @@ void relay_destroy_channel(struct kref *kref)
420void relay_close(struct rchan *chan) 431void relay_close(struct rchan *chan)
421{ 432{
422 unsigned int i; 433 unsigned int i;
434 struct rchan_buf *prev = NULL;
423 435
424 if (!chan) 436 if (!chan)
425 return; 437 return;
426 438
427 for (i = 0; i < NR_CPUS; i++) { 439 for (i = 0; i < NR_CPUS; i++) {
428 if (!chan->buf[i]) 440 if (!chan->buf[i] || chan->buf[i] == prev)
429 continue; 441 break;
430 relay_close_buf(chan->buf[i]); 442 relay_close_buf(chan->buf[i]);
443 prev = chan->buf[i];
431 } 444 }
432 445
433 if (chan->last_toobig) 446 if (chan->last_toobig)
@@ -447,14 +460,16 @@ void relay_close(struct rchan *chan)
447void relay_flush(struct rchan *chan) 460void relay_flush(struct rchan *chan)
448{ 461{
449 unsigned int i; 462 unsigned int i;
463 struct rchan_buf *prev = NULL;
450 464
451 if (!chan) 465 if (!chan)
452 return; 466 return;
453 467
454 for (i = 0; i < NR_CPUS; i++) { 468 for (i = 0; i < NR_CPUS; i++) {
455 if (!chan->buf[i]) 469 if (!chan->buf[i] || chan->buf[i] == prev)
456 continue; 470 break;
457 relay_switch_subbuf(chan->buf[i], 0); 471 relay_switch_subbuf(chan->buf[i], 0);
472 prev = chan->buf[i];
458 } 473 }
459} 474}
460 475
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h
index 8c2177105857..30f45511b40d 100644
--- a/include/linux/relayfs_fs.h
+++ b/include/linux/relayfs_fs.h
@@ -116,6 +116,7 @@ struct rchan_callbacks
116 * @parent: the parent of the file to create 116 * @parent: the parent of the file to create
117 * @mode: the mode of the file to create 117 * @mode: the mode of the file to create
118 * @buf: the channel buffer 118 * @buf: the channel buffer
119 * @is_global: outparam - set non-zero if the buffer should be global
119 * 120 *
120 * Called during relay_open(), once for each per-cpu buffer, 121 * Called during relay_open(), once for each per-cpu buffer,
121 * to allow the client to create a file to be used to 122 * to allow the client to create a file to be used to
@@ -126,12 +127,17 @@ struct rchan_callbacks
126 * The callback should return the dentry of the file created 127 * The callback should return the dentry of the file created
127 * to represent the relay buffer. 128 * to represent the relay buffer.
128 * 129 *
130 * Setting the is_global outparam to a non-zero value will
131 * cause relay_open() to create a single global buffer rather
132 * than the default set of per-cpu buffers.
133 *
129 * See Documentation/filesystems/relayfs.txt for more info. 134 * See Documentation/filesystems/relayfs.txt for more info.
130 */ 135 */
131 struct dentry *(*create_buf_file)(const char *filename, 136 struct dentry *(*create_buf_file)(const char *filename,
132 struct dentry *parent, 137 struct dentry *parent,
133 int mode, 138 int mode,
134 struct rchan_buf *buf); 139 struct rchan_buf *buf,
140 int *is_global);
135 141
136 /* 142 /*
137 * remove_buf_file - remove file representing a relayfs channel buffer 143 * remove_buf_file - remove file representing a relayfs channel buffer