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 | ||
