diff options
Diffstat (limited to 'fs/relayfs/relay.c')
| -rw-r--r-- | fs/relayfs/relay.c | 69 |
1 files changed, 58 insertions, 11 deletions
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c index 2a6f7f12b7f9..abf3ceaace49 100644 --- a/fs/relayfs/relay.c +++ b/fs/relayfs/relay.c | |||
| @@ -80,11 +80,34 @@ static void buf_unmapped_default_callback(struct rchan_buf *buf, | |||
| 80 | { | 80 | { |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | /* | ||
| 84 | * create_buf_file_create() default callback. Creates file to represent buf. | ||
| 85 | */ | ||
| 86 | static struct dentry *create_buf_file_default_callback(const char *filename, | ||
| 87 | struct dentry *parent, | ||
| 88 | int mode, | ||
| 89 | struct rchan_buf *buf, | ||
| 90 | int *is_global) | ||
| 91 | { | ||
| 92 | return relayfs_create_file(filename, parent, mode, | ||
| 93 | &relay_file_operations, buf); | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | ||
| 97 | * remove_buf_file() default callback. Removes file representing relay buffer. | ||
| 98 | */ | ||
| 99 | static int remove_buf_file_default_callback(struct dentry *dentry) | ||
| 100 | { | ||
| 101 | return relayfs_remove(dentry); | ||
| 102 | } | ||
| 103 | |||
| 83 | /* relay channel default callbacks */ | 104 | /* relay channel default callbacks */ |
| 84 | static struct rchan_callbacks default_channel_callbacks = { | 105 | static struct rchan_callbacks default_channel_callbacks = { |
| 85 | .subbuf_start = subbuf_start_default_callback, | 106 | .subbuf_start = subbuf_start_default_callback, |
| 86 | .buf_mapped = buf_mapped_default_callback, | 107 | .buf_mapped = buf_mapped_default_callback, |
| 87 | .buf_unmapped = buf_unmapped_default_callback, | 108 | .buf_unmapped = buf_unmapped_default_callback, |
| 109 | .create_buf_file = create_buf_file_default_callback, | ||
| 110 | .remove_buf_file = remove_buf_file_default_callback, | ||
| 88 | }; | 111 | }; |
| 89 | 112 | ||
| 90 | /** | 113 | /** |
| @@ -148,14 +171,16 @@ static inline void __relay_reset(struct rchan_buf *buf, unsigned int init) | |||
| 148 | void relay_reset(struct rchan *chan) | 171 | void relay_reset(struct rchan *chan) |
| 149 | { | 172 | { |
| 150 | unsigned int i; | 173 | unsigned int i; |
| 174 | struct rchan_buf *prev = NULL; | ||
| 151 | 175 | ||
| 152 | if (!chan) | 176 | if (!chan) |
| 153 | return; | 177 | return; |
| 154 | 178 | ||
| 155 | for (i = 0; i < NR_CPUS; i++) { | 179 | for (i = 0; i < NR_CPUS; i++) { |
| 156 | if (!chan->buf[i]) | 180 | if (!chan->buf[i] || chan->buf[i] == prev) |
| 157 | continue; | 181 | break; |
| 158 | __relay_reset(chan->buf[i], 0); | 182 | __relay_reset(chan->buf[i], 0); |
| 183 | prev = chan->buf[i]; | ||
| 159 | } | 184 | } |
| 160 | } | 185 | } |
| 161 | 186 | ||
| @@ -166,17 +191,27 @@ void relay_reset(struct rchan *chan) | |||
| 166 | */ | 191 | */ |
| 167 | static struct rchan_buf *relay_open_buf(struct rchan *chan, | 192 | static struct rchan_buf *relay_open_buf(struct rchan *chan, |
| 168 | const char *filename, | 193 | const char *filename, |
| 169 | struct dentry *parent) | 194 | struct dentry *parent, |
| 195 | int *is_global) | ||
| 170 | { | 196 | { |
| 171 | struct rchan_buf *buf; | 197 | struct rchan_buf *buf; |
| 172 | struct dentry *dentry; | 198 | struct dentry *dentry; |
| 173 | 199 | ||
| 200 | if (*is_global) | ||
| 201 | return chan->buf[0]; | ||
| 202 | |||
| 203 | buf = relay_create_buf(chan); | ||
| 204 | if (!buf) | ||
| 205 | return NULL; | ||
| 206 | |||
| 174 | /* Create file in fs */ | 207 | /* Create file in fs */ |
| 175 | dentry = relayfs_create_file(filename, parent, S_IRUSR, chan); | 208 | dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR, |
| 176 | if (!dentry) | 209 | buf, is_global); |
| 210 | if (!dentry) { | ||
| 211 | relay_destroy_buf(buf); | ||
| 177 | return NULL; | 212 | return NULL; |
| 213 | } | ||
| 178 | 214 | ||
| 179 | buf = RELAYFS_I(dentry->d_inode)->buf; | ||
| 180 | buf->dentry = dentry; | 215 | buf->dentry = dentry; |
| 181 | __relay_reset(buf, 1); | 216 | __relay_reset(buf, 1); |
| 182 | 217 | ||
| @@ -214,6 +249,10 @@ static inline void setup_callbacks(struct rchan *chan, | |||
| 214 | cb->buf_mapped = buf_mapped_default_callback; | 249 | cb->buf_mapped = buf_mapped_default_callback; |
| 215 | if (!cb->buf_unmapped) | 250 | if (!cb->buf_unmapped) |
| 216 | cb->buf_unmapped = buf_unmapped_default_callback; | 251 | cb->buf_unmapped = buf_unmapped_default_callback; |
| 252 | if (!cb->create_buf_file) | ||
| 253 | cb->create_buf_file = create_buf_file_default_callback; | ||
| 254 | if (!cb->remove_buf_file) | ||
| 255 | cb->remove_buf_file = remove_buf_file_default_callback; | ||
| 217 | chan->cb = cb; | 256 | chan->cb = cb; |
| 218 | } | 257 | } |
| 219 | 258 | ||
| @@ -241,6 +280,7 @@ struct rchan *relay_open(const char *base_filename, | |||
| 241 | unsigned int i; | 280 | unsigned int i; |
| 242 | struct rchan *chan; | 281 | struct rchan *chan; |
| 243 | char *tmpname; | 282 | char *tmpname; |
| 283 | int is_global = 0; | ||
| 244 | 284 | ||
| 245 | if (!base_filename) | 285 | if (!base_filename) |
| 246 | return NULL; | 286 | return NULL; |
| @@ -265,7 +305,8 @@ struct rchan *relay_open(const char *base_filename, | |||
| 265 | 305 | ||
| 266 | for_each_online_cpu(i) { | 306 | for_each_online_cpu(i) { |
| 267 | sprintf(tmpname, "%s%d", base_filename, i); | 307 | sprintf(tmpname, "%s%d", base_filename, i); |
| 268 | chan->buf[i] = relay_open_buf(chan, tmpname, parent); | 308 | chan->buf[i] = relay_open_buf(chan, tmpname, parent, |
| 309 | &is_global); | ||
| 269 | chan->buf[i]->cpu = i; | 310 | chan->buf[i]->cpu = i; |
| 270 | if (!chan->buf[i]) | 311 | if (!chan->buf[i]) |
| 271 | goto free_bufs; | 312 | goto free_bufs; |
| @@ -279,6 +320,8 @@ free_bufs: | |||
| 279 | if (!chan->buf[i]) | 320 | if (!chan->buf[i]) |
| 280 | break; | 321 | break; |
| 281 | relay_close_buf(chan->buf[i]); | 322 | relay_close_buf(chan->buf[i]); |
| 323 | if (is_global) | ||
| 324 | break; | ||
| 282 | } | 325 | } |
| 283 | kfree(tmpname); | 326 | kfree(tmpname); |
| 284 | 327 | ||
| @@ -388,14 +431,16 @@ void relay_destroy_channel(struct kref *kref) | |||
| 388 | void relay_close(struct rchan *chan) | 431 | void relay_close(struct rchan *chan) |
| 389 | { | 432 | { |
| 390 | unsigned int i; | 433 | unsigned int i; |
| 434 | struct rchan_buf *prev = NULL; | ||
| 391 | 435 | ||
| 392 | if (!chan) | 436 | if (!chan) |
| 393 | return; | 437 | return; |
| 394 | 438 | ||
| 395 | for (i = 0; i < NR_CPUS; i++) { | 439 | for (i = 0; i < NR_CPUS; i++) { |
| 396 | if (!chan->buf[i]) | 440 | if (!chan->buf[i] || chan->buf[i] == prev) |
| 397 | continue; | 441 | break; |
| 398 | relay_close_buf(chan->buf[i]); | 442 | relay_close_buf(chan->buf[i]); |
| 443 | prev = chan->buf[i]; | ||
| 399 | } | 444 | } |
| 400 | 445 | ||
| 401 | if (chan->last_toobig) | 446 | if (chan->last_toobig) |
| @@ -415,14 +460,16 @@ void relay_close(struct rchan *chan) | |||
| 415 | void relay_flush(struct rchan *chan) | 460 | void relay_flush(struct rchan *chan) |
| 416 | { | 461 | { |
| 417 | unsigned int i; | 462 | unsigned int i; |
| 463 | struct rchan_buf *prev = NULL; | ||
| 418 | 464 | ||
| 419 | if (!chan) | 465 | if (!chan) |
| 420 | return; | 466 | return; |
| 421 | 467 | ||
| 422 | for (i = 0; i < NR_CPUS; i++) { | 468 | for (i = 0; i < NR_CPUS; i++) { |
| 423 | if (!chan->buf[i]) | 469 | if (!chan->buf[i] || chan->buf[i] == prev) |
| 424 | continue; | 470 | break; |
| 425 | relay_switch_subbuf(chan->buf[i], 0); | 471 | relay_switch_subbuf(chan->buf[i], 0); |
| 472 | prev = chan->buf[i]; | ||
| 426 | } | 473 | } |
| 427 | } | 474 | } |
| 428 | 475 | ||
