diff options
-rw-r--r-- | fs/relayfs/relay.c | 35 | ||||
-rw-r--r-- | include/linux/relayfs_fs.h | 8 |
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, | |||
86 | static struct dentry *create_buf_file_default_callback(const char *filename, | 86 | static 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) | |||
170 | void relay_reset(struct rchan *chan) | 171 | void 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 | */ |
189 | static struct rchan_buf *relay_open_buf(struct rchan *chan, | 192 | static 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) | |||
420 | void relay_close(struct rchan *chan) | 431 | void 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) | |||
447 | void relay_flush(struct rchan *chan) | 460 | void 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 |