aboutsummaryrefslogtreecommitdiffstats
path: root/fs/relayfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/relayfs')
-rw-r--r--fs/relayfs/buffers.c3
-rw-r--r--fs/relayfs/inode.c226
-rw-r--r--fs/relayfs/relay.c77
-rw-r--r--fs/relayfs/relay.h4
4 files changed, 165 insertions, 145 deletions
diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c
index 84e21ffa5ca8..10187812771e 100644
--- a/fs/relayfs/buffers.c
+++ b/fs/relayfs/buffers.c
@@ -185,5 +185,6 @@ void relay_destroy_buf(struct rchan_buf *buf)
185void relay_remove_buf(struct kref *kref) 185void relay_remove_buf(struct kref *kref)
186{ 186{
187 struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref); 187 struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
188 relayfs_remove(buf->dentry); 188 buf->chan->cb->remove_buf_file(buf->dentry);
189 relay_destroy_buf(buf);
189} 190}
diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
index 0f7f88d067ad..383523011aad 100644
--- a/fs/relayfs/inode.c
+++ b/fs/relayfs/inode.c
@@ -26,31 +26,22 @@
26 26
27static struct vfsmount * relayfs_mount; 27static struct vfsmount * relayfs_mount;
28static int relayfs_mount_count; 28static int relayfs_mount_count;
29static kmem_cache_t * relayfs_inode_cachep;
30 29
31static struct backing_dev_info relayfs_backing_dev_info = { 30static struct backing_dev_info relayfs_backing_dev_info = {
32 .ra_pages = 0, /* No readahead */ 31 .ra_pages = 0, /* No readahead */
33 .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, 32 .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
34}; 33};
35 34
36static struct inode *relayfs_get_inode(struct super_block *sb, int mode, 35static struct inode *relayfs_get_inode(struct super_block *sb,
37 struct rchan *chan) 36 int mode,
37 struct file_operations *fops,
38 void *data)
38{ 39{
39 struct rchan_buf *buf = NULL;
40 struct inode *inode; 40 struct inode *inode;
41 41
42 if (S_ISREG(mode)) {
43 BUG_ON(!chan);
44 buf = relay_create_buf(chan);
45 if (!buf)
46 return NULL;
47 }
48
49 inode = new_inode(sb); 42 inode = new_inode(sb);
50 if (!inode) { 43 if (!inode)
51 relay_destroy_buf(buf);
52 return NULL; 44 return NULL;
53 }
54 45
55 inode->i_mode = mode; 46 inode->i_mode = mode;
56 inode->i_uid = 0; 47 inode->i_uid = 0;
@@ -61,8 +52,9 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
61 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 52 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
62 switch (mode & S_IFMT) { 53 switch (mode & S_IFMT) {
63 case S_IFREG: 54 case S_IFREG:
64 inode->i_fop = &relayfs_file_operations; 55 inode->i_fop = fops;
65 RELAYFS_I(inode)->buf = buf; 56 if (data)
57 inode->u.generic_ip = data;
66 break; 58 break;
67 case S_IFDIR: 59 case S_IFDIR:
68 inode->i_op = &simple_dir_inode_operations; 60 inode->i_op = &simple_dir_inode_operations;
@@ -83,7 +75,8 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
83 * @name: the name of the file to create 75 * @name: the name of the file to create
84 * @parent: parent directory 76 * @parent: parent directory
85 * @mode: mode 77 * @mode: mode
86 * @chan: relay channel associated with the file 78 * @fops: file operations to use for the file
79 * @data: user-associated data for this file
87 * 80 *
88 * Returns the new dentry, NULL on failure 81 * Returns the new dentry, NULL on failure
89 * 82 *
@@ -92,7 +85,8 @@ static struct inode *relayfs_get_inode(struct super_block *sb, int mode,
92static struct dentry *relayfs_create_entry(const char *name, 85static struct dentry *relayfs_create_entry(const char *name,
93 struct dentry *parent, 86 struct dentry *parent,
94 int mode, 87 int mode,
95 struct rchan *chan) 88 struct file_operations *fops,
89 void *data)
96{ 90{
97 struct dentry *d; 91 struct dentry *d;
98 struct inode *inode; 92 struct inode *inode;
@@ -115,7 +109,7 @@ static struct dentry *relayfs_create_entry(const char *name,
115 } 109 }
116 110
117 parent = dget(parent); 111 parent = dget(parent);
118 down(&parent->d_inode->i_sem); 112 mutex_lock(&parent->d_inode->i_mutex);
119 d = lookup_one_len(name, parent, strlen(name)); 113 d = lookup_one_len(name, parent, strlen(name));
120 if (IS_ERR(d)) { 114 if (IS_ERR(d)) {
121 d = NULL; 115 d = NULL;
@@ -127,7 +121,7 @@ static struct dentry *relayfs_create_entry(const char *name,
127 goto release_mount; 121 goto release_mount;
128 } 122 }
129 123
130 inode = relayfs_get_inode(parent->d_inode->i_sb, mode, chan); 124 inode = relayfs_get_inode(parent->d_inode->i_sb, mode, fops, data);
131 if (!inode) { 125 if (!inode) {
132 d = NULL; 126 d = NULL;
133 goto release_mount; 127 goto release_mount;
@@ -145,7 +139,7 @@ release_mount:
145 simple_release_fs(&relayfs_mount, &relayfs_mount_count); 139 simple_release_fs(&relayfs_mount, &relayfs_mount_count);
146 140
147exit: 141exit:
148 up(&parent->d_inode->i_sem); 142 mutex_unlock(&parent->d_inode->i_mutex);
149 dput(parent); 143 dput(parent);
150 return d; 144 return d;
151} 145}
@@ -155,20 +149,26 @@ exit:
155 * @name: the name of the file to create 149 * @name: the name of the file to create
156 * @parent: parent directory 150 * @parent: parent directory
157 * @mode: mode, if not specied the default perms are used 151 * @mode: mode, if not specied the default perms are used
158 * @chan: channel associated with the file 152 * @fops: file operations to use for the file
153 * @data: user-associated data for this file
159 * 154 *
160 * Returns file dentry if successful, NULL otherwise. 155 * Returns file dentry if successful, NULL otherwise.
161 * 156 *
162 * The file will be created user r on behalf of current user. 157 * The file will be created user r on behalf of current user.
163 */ 158 */
164struct dentry *relayfs_create_file(const char *name, struct dentry *parent, 159struct dentry *relayfs_create_file(const char *name,
165 int mode, struct rchan *chan) 160 struct dentry *parent,
161 int mode,
162 struct file_operations *fops,
163 void *data)
166{ 164{
165 BUG_ON(!fops);
166
167 if (!mode) 167 if (!mode)
168 mode = S_IRUSR; 168 mode = S_IRUSR;
169 mode = (mode & S_IALLUGO) | S_IFREG; 169 mode = (mode & S_IALLUGO) | S_IFREG;
170 170
171 return relayfs_create_entry(name, parent, mode, chan); 171 return relayfs_create_entry(name, parent, mode, fops, data);
172} 172}
173 173
174/** 174/**
@@ -183,7 +183,7 @@ struct dentry *relayfs_create_file(const char *name, struct dentry *parent,
183struct dentry *relayfs_create_dir(const char *name, struct dentry *parent) 183struct dentry *relayfs_create_dir(const char *name, struct dentry *parent)
184{ 184{
185 int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO; 185 int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
186 return relayfs_create_entry(name, parent, mode, NULL); 186 return relayfs_create_entry(name, parent, mode, NULL, NULL);
187} 187}
188 188
189/** 189/**
@@ -204,7 +204,7 @@ int relayfs_remove(struct dentry *dentry)
204 return -EINVAL; 204 return -EINVAL;
205 205
206 parent = dget(parent); 206 parent = dget(parent);
207 down(&parent->d_inode->i_sem); 207 mutex_lock(&parent->d_inode->i_mutex);
208 if (dentry->d_inode) { 208 if (dentry->d_inode) {
209 if (S_ISDIR(dentry->d_inode->i_mode)) 209 if (S_ISDIR(dentry->d_inode->i_mode))
210 error = simple_rmdir(parent->d_inode, dentry); 210 error = simple_rmdir(parent->d_inode, dentry);
@@ -215,7 +215,7 @@ int relayfs_remove(struct dentry *dentry)
215 } 215 }
216 if (!error) 216 if (!error)
217 dput(dentry); 217 dput(dentry);
218 up(&parent->d_inode->i_sem); 218 mutex_unlock(&parent->d_inode->i_mutex);
219 dput(parent); 219 dput(parent);
220 220
221 if (!error) 221 if (!error)
@@ -225,6 +225,17 @@ int relayfs_remove(struct dentry *dentry)
225} 225}
226 226
227/** 227/**
228 * relayfs_remove_file - remove a file from relay filesystem
229 * @dentry: directory dentry
230 *
231 * Returns 0 if successful, negative otherwise.
232 */
233int relayfs_remove_file(struct dentry *dentry)
234{
235 return relayfs_remove(dentry);
236}
237
238/**
228 * relayfs_remove_dir - remove a directory in the relay filesystem 239 * relayfs_remove_dir - remove a directory in the relay filesystem
229 * @dentry: directory dentry 240 * @dentry: directory dentry
230 * 241 *
@@ -236,45 +247,45 @@ int relayfs_remove_dir(struct dentry *dentry)
236} 247}
237 248
238/** 249/**
239 * relayfs_open - open file op for relayfs files 250 * relay_file_open - open file op for relay files
240 * @inode: the inode 251 * @inode: the inode
241 * @filp: the file 252 * @filp: the file
242 * 253 *
243 * Increments the channel buffer refcount. 254 * Increments the channel buffer refcount.
244 */ 255 */
245static int relayfs_open(struct inode *inode, struct file *filp) 256static int relay_file_open(struct inode *inode, struct file *filp)
246{ 257{
247 struct rchan_buf *buf = RELAYFS_I(inode)->buf; 258 struct rchan_buf *buf = inode->u.generic_ip;
248 kref_get(&buf->kref); 259 kref_get(&buf->kref);
260 filp->private_data = buf;
249 261
250 return 0; 262 return 0;
251} 263}
252 264
253/** 265/**
254 * relayfs_mmap - mmap file op for relayfs files 266 * relay_file_mmap - mmap file op for relay files
255 * @filp: the file 267 * @filp: the file
256 * @vma: the vma describing what to map 268 * @vma: the vma describing what to map
257 * 269 *
258 * Calls upon relay_mmap_buf to map the file into user space. 270 * Calls upon relay_mmap_buf to map the file into user space.
259 */ 271 */
260static int relayfs_mmap(struct file *filp, struct vm_area_struct *vma) 272static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma)
261{ 273{
262 struct inode *inode = filp->f_dentry->d_inode; 274 struct rchan_buf *buf = filp->private_data;
263 return relay_mmap_buf(RELAYFS_I(inode)->buf, vma); 275 return relay_mmap_buf(buf, vma);
264} 276}
265 277
266/** 278/**
267 * relayfs_poll - poll file op for relayfs files 279 * relay_file_poll - poll file op for relay files
268 * @filp: the file 280 * @filp: the file
269 * @wait: poll table 281 * @wait: poll table
270 * 282 *
271 * Poll implemention. 283 * Poll implemention.
272 */ 284 */
273static unsigned int relayfs_poll(struct file *filp, poll_table *wait) 285static unsigned int relay_file_poll(struct file *filp, poll_table *wait)
274{ 286{
275 unsigned int mask = 0; 287 unsigned int mask = 0;
276 struct inode *inode = filp->f_dentry->d_inode; 288 struct rchan_buf *buf = filp->private_data;
277 struct rchan_buf *buf = RELAYFS_I(inode)->buf;
278 289
279 if (buf->finalized) 290 if (buf->finalized)
280 return POLLERR; 291 return POLLERR;
@@ -289,27 +300,27 @@ static unsigned int relayfs_poll(struct file *filp, poll_table *wait)
289} 300}
290 301
291/** 302/**
292 * relayfs_release - release file op for relayfs files 303 * relay_file_release - release file op for relay files
293 * @inode: the inode 304 * @inode: the inode
294 * @filp: the file 305 * @filp: the file
295 * 306 *
296 * Decrements the channel refcount, as the filesystem is 307 * Decrements the channel refcount, as the filesystem is
297 * no longer using it. 308 * no longer using it.
298 */ 309 */
299static int relayfs_release(struct inode *inode, struct file *filp) 310static int relay_file_release(struct inode *inode, struct file *filp)
300{ 311{
301 struct rchan_buf *buf = RELAYFS_I(inode)->buf; 312 struct rchan_buf *buf = filp->private_data;
302 kref_put(&buf->kref, relay_remove_buf); 313 kref_put(&buf->kref, relay_remove_buf);
303 314
304 return 0; 315 return 0;
305} 316}
306 317
307/** 318/**
308 * relayfs_read_consume - update the consumed count for the buffer 319 * relay_file_read_consume - update the consumed count for the buffer
309 */ 320 */
310static void relayfs_read_consume(struct rchan_buf *buf, 321static void relay_file_read_consume(struct rchan_buf *buf,
311 size_t read_pos, 322 size_t read_pos,
312 size_t bytes_consumed) 323 size_t bytes_consumed)
313{ 324{
314 size_t subbuf_size = buf->chan->subbuf_size; 325 size_t subbuf_size = buf->chan->subbuf_size;
315 size_t n_subbufs = buf->chan->n_subbufs; 326 size_t n_subbufs = buf->chan->n_subbufs;
@@ -332,9 +343,9 @@ static void relayfs_read_consume(struct rchan_buf *buf,
332} 343}
333 344
334/** 345/**
335 * relayfs_read_avail - boolean, are there unconsumed bytes available? 346 * relay_file_read_avail - boolean, are there unconsumed bytes available?
336 */ 347 */
337static int relayfs_read_avail(struct rchan_buf *buf, size_t read_pos) 348static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
338{ 349{
339 size_t bytes_produced, bytes_consumed, write_offset; 350 size_t bytes_produced, bytes_consumed, write_offset;
340 size_t subbuf_size = buf->chan->subbuf_size; 351 size_t subbuf_size = buf->chan->subbuf_size;
@@ -365,16 +376,16 @@ static int relayfs_read_avail(struct rchan_buf *buf, size_t read_pos)
365 if (bytes_produced == bytes_consumed) 376 if (bytes_produced == bytes_consumed)
366 return 0; 377 return 0;
367 378
368 relayfs_read_consume(buf, read_pos, 0); 379 relay_file_read_consume(buf, read_pos, 0);
369 380
370 return 1; 381 return 1;
371} 382}
372 383
373/** 384/**
374 * relayfs_read_subbuf_avail - return bytes available in sub-buffer 385 * relay_file_read_subbuf_avail - return bytes available in sub-buffer
375 */ 386 */
376static size_t relayfs_read_subbuf_avail(size_t read_pos, 387static size_t relay_file_read_subbuf_avail(size_t read_pos,
377 struct rchan_buf *buf) 388 struct rchan_buf *buf)
378{ 389{
379 size_t padding, avail = 0; 390 size_t padding, avail = 0;
380 size_t read_subbuf, read_offset, write_subbuf, write_offset; 391 size_t read_subbuf, read_offset, write_subbuf, write_offset;
@@ -396,14 +407,14 @@ static size_t relayfs_read_subbuf_avail(size_t read_pos,
396} 407}
397 408
398/** 409/**
399 * relayfs_read_start_pos - find the first available byte to read 410 * relay_file_read_start_pos - find the first available byte to read
400 * 411 *
401 * If the read_pos is in the middle of padding, return the 412 * If the read_pos is in the middle of padding, return the
402 * position of the first actually available byte, otherwise 413 * position of the first actually available byte, otherwise
403 * return the original value. 414 * return the original value.
404 */ 415 */
405static size_t relayfs_read_start_pos(size_t read_pos, 416static size_t relay_file_read_start_pos(size_t read_pos,
406 struct rchan_buf *buf) 417 struct rchan_buf *buf)
407{ 418{
408 size_t read_subbuf, padding, padding_start, padding_end; 419 size_t read_subbuf, padding, padding_start, padding_end;
409 size_t subbuf_size = buf->chan->subbuf_size; 420 size_t subbuf_size = buf->chan->subbuf_size;
@@ -422,11 +433,11 @@ static size_t relayfs_read_start_pos(size_t read_pos,
422} 433}
423 434
424/** 435/**
425 * relayfs_read_end_pos - return the new read position 436 * relay_file_read_end_pos - return the new read position
426 */ 437 */
427static size_t relayfs_read_end_pos(struct rchan_buf *buf, 438static size_t relay_file_read_end_pos(struct rchan_buf *buf,
428 size_t read_pos, 439 size_t read_pos,
429 size_t count) 440 size_t count)
430{ 441{
431 size_t read_subbuf, padding, end_pos; 442 size_t read_subbuf, padding, end_pos;
432 size_t subbuf_size = buf->chan->subbuf_size; 443 size_t subbuf_size = buf->chan->subbuf_size;
@@ -445,7 +456,7 @@ static size_t relayfs_read_end_pos(struct rchan_buf *buf,
445} 456}
446 457
447/** 458/**
448 * relayfs_read - read file op for relayfs files 459 * relay_file_read - read file op for relay files
449 * @filp: the file 460 * @filp: the file
450 * @buffer: the userspace buffer 461 * @buffer: the userspace buffer
451 * @count: number of bytes to read 462 * @count: number of bytes to read
@@ -454,23 +465,23 @@ static size_t relayfs_read_end_pos(struct rchan_buf *buf,
454 * Reads count bytes or the number of bytes available in the 465 * Reads count bytes or the number of bytes available in the
455 * current sub-buffer being read, whichever is smaller. 466 * current sub-buffer being read, whichever is smaller.
456 */ 467 */
457static ssize_t relayfs_read(struct file *filp, 468static ssize_t relay_file_read(struct file *filp,
458 char __user *buffer, 469 char __user *buffer,
459 size_t count, 470 size_t count,
460 loff_t *ppos) 471 loff_t *ppos)
461{ 472{
473 struct rchan_buf *buf = filp->private_data;
462 struct inode *inode = filp->f_dentry->d_inode; 474 struct inode *inode = filp->f_dentry->d_inode;
463 struct rchan_buf *buf = RELAYFS_I(inode)->buf;
464 size_t read_start, avail; 475 size_t read_start, avail;
465 ssize_t ret = 0; 476 ssize_t ret = 0;
466 void *from; 477 void *from;
467 478
468 down(&inode->i_sem); 479 mutex_lock(&inode->i_mutex);
469 if(!relayfs_read_avail(buf, *ppos)) 480 if(!relay_file_read_avail(buf, *ppos))
470 goto out; 481 goto out;
471 482
472 read_start = relayfs_read_start_pos(*ppos, buf); 483 read_start = relay_file_read_start_pos(*ppos, buf);
473 avail = relayfs_read_subbuf_avail(read_start, buf); 484 avail = relay_file_read_subbuf_avail(read_start, buf);
474 if (!avail) 485 if (!avail)
475 goto out; 486 goto out;
476 487
@@ -480,58 +491,25 @@ static ssize_t relayfs_read(struct file *filp,
480 ret = -EFAULT; 491 ret = -EFAULT;
481 goto out; 492 goto out;
482 } 493 }
483 relayfs_read_consume(buf, read_start, count); 494 relay_file_read_consume(buf, read_start, count);
484 *ppos = relayfs_read_end_pos(buf, read_start, count); 495 *ppos = relay_file_read_end_pos(buf, read_start, count);
485out: 496out:
486 up(&inode->i_sem); 497 mutex_unlock(&inode->i_mutex);
487 return ret; 498 return ret;
488} 499}
489 500
490/** 501struct file_operations relay_file_operations = {
491 * relayfs alloc_inode() implementation 502 .open = relay_file_open,
492 */ 503 .poll = relay_file_poll,
493static struct inode *relayfs_alloc_inode(struct super_block *sb) 504 .mmap = relay_file_mmap,
494{ 505 .read = relay_file_read,
495 struct relayfs_inode_info *p = kmem_cache_alloc(relayfs_inode_cachep, SLAB_KERNEL);
496 if (!p)
497 return NULL;
498 p->buf = NULL;
499
500 return &p->vfs_inode;
501}
502
503/**
504 * relayfs destroy_inode() implementation
505 */
506static void relayfs_destroy_inode(struct inode *inode)
507{
508 if (RELAYFS_I(inode)->buf)
509 relay_destroy_buf(RELAYFS_I(inode)->buf);
510
511 kmem_cache_free(relayfs_inode_cachep, RELAYFS_I(inode));
512}
513
514static void init_once(void *p, kmem_cache_t *cachep, unsigned long flags)
515{
516 struct relayfs_inode_info *i = p;
517 if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR)
518 inode_init_once(&i->vfs_inode);
519}
520
521struct file_operations relayfs_file_operations = {
522 .open = relayfs_open,
523 .poll = relayfs_poll,
524 .mmap = relayfs_mmap,
525 .read = relayfs_read,
526 .llseek = no_llseek, 506 .llseek = no_llseek,
527 .release = relayfs_release, 507 .release = relay_file_release,
528}; 508};
529 509
530static struct super_operations relayfs_ops = { 510static struct super_operations relayfs_ops = {
531 .statfs = simple_statfs, 511 .statfs = simple_statfs,
532 .drop_inode = generic_delete_inode, 512 .drop_inode = generic_delete_inode,
533 .alloc_inode = relayfs_alloc_inode,
534 .destroy_inode = relayfs_destroy_inode,
535}; 513};
536 514
537static int relayfs_fill_super(struct super_block * sb, void * data, int silent) 515static int relayfs_fill_super(struct super_block * sb, void * data, int silent)
@@ -544,7 +522,7 @@ static int relayfs_fill_super(struct super_block * sb, void * data, int silent)
544 sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 522 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
545 sb->s_magic = RELAYFS_MAGIC; 523 sb->s_magic = RELAYFS_MAGIC;
546 sb->s_op = &relayfs_ops; 524 sb->s_op = &relayfs_ops;
547 inode = relayfs_get_inode(sb, mode, NULL); 525 inode = relayfs_get_inode(sb, mode, NULL, NULL);
548 526
549 if (!inode) 527 if (!inode)
550 return -ENOMEM; 528 return -ENOMEM;
@@ -575,33 +553,27 @@ static struct file_system_type relayfs_fs_type = {
575 553
576static int __init init_relayfs_fs(void) 554static int __init init_relayfs_fs(void)
577{ 555{
578 int err; 556 return register_filesystem(&relayfs_fs_type);
579
580 relayfs_inode_cachep = kmem_cache_create("relayfs_inode_cache",
581 sizeof(struct relayfs_inode_info), 0,
582 0, init_once, NULL);
583 if (!relayfs_inode_cachep)
584 return -ENOMEM;
585
586 err = register_filesystem(&relayfs_fs_type);
587 if (err)
588 kmem_cache_destroy(relayfs_inode_cachep);
589
590 return err;
591} 557}
592 558
593static void __exit exit_relayfs_fs(void) 559static void __exit exit_relayfs_fs(void)
594{ 560{
561
562
563
564
565
595 unregister_filesystem(&relayfs_fs_type); 566 unregister_filesystem(&relayfs_fs_type);
596 kmem_cache_destroy(relayfs_inode_cachep);
597} 567}
598 568
599module_init(init_relayfs_fs) 569module_init(init_relayfs_fs)
600module_exit(exit_relayfs_fs) 570module_exit(exit_relayfs_fs)
601 571
602EXPORT_SYMBOL_GPL(relayfs_file_operations); 572EXPORT_SYMBOL_GPL(relay_file_operations);
603EXPORT_SYMBOL_GPL(relayfs_create_dir); 573EXPORT_SYMBOL_GPL(relayfs_create_dir);
604EXPORT_SYMBOL_GPL(relayfs_remove_dir); 574EXPORT_SYMBOL_GPL(relayfs_remove_dir);
575EXPORT_SYMBOL_GPL(relayfs_create_file);
576EXPORT_SYMBOL_GPL(relayfs_remove_file);
605 577
606MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>"); 578MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>");
607MODULE_DESCRIPTION("Relay Filesystem"); 579MODULE_DESCRIPTION("Relay Filesystem");
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
index 16446a15c96d..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 */
86static 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 */
99static 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 */
84static struct rchan_callbacks default_channel_callbacks = { 105static 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)
148void relay_reset(struct rchan *chan) 171void 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 */
167static struct rchan_buf *relay_open_buf(struct rchan *chan, 192static 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
@@ -333,8 +376,7 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
333 return length; 376 return length;
334 377
335toobig: 378toobig:
336 printk(KERN_WARNING "relayfs: event too large (%Zd)\n", length); 379 buf->chan->last_toobig = length;
337 WARN_ON(1);
338 return 0; 380 return 0;
339} 381}
340 382
@@ -389,16 +431,23 @@ void relay_destroy_channel(struct kref *kref)
389void relay_close(struct rchan *chan) 431void relay_close(struct rchan *chan)
390{ 432{
391 unsigned int i; 433 unsigned int i;
434 struct rchan_buf *prev = NULL;
392 435
393 if (!chan) 436 if (!chan)
394 return; 437 return;
395 438
396 for (i = 0; i < NR_CPUS; i++) { 439 for (i = 0; i < NR_CPUS; i++) {
397 if (!chan->buf[i]) 440 if (!chan->buf[i] || chan->buf[i] == prev)
398 continue; 441 break;
399 relay_close_buf(chan->buf[i]); 442 relay_close_buf(chan->buf[i]);
443 prev = chan->buf[i];
400 } 444 }
401 445
446 if (chan->last_toobig)
447 printk(KERN_WARNING "relayfs: one or more items not logged "
448 "[item size (%Zd) > sub-buffer size (%Zd)]\n",
449 chan->last_toobig, chan->subbuf_size);
450
402 kref_put(&chan->kref, relay_destroy_channel); 451 kref_put(&chan->kref, relay_destroy_channel);
403} 452}
404 453
@@ -411,14 +460,16 @@ void relay_close(struct rchan *chan)
411void relay_flush(struct rchan *chan) 460void relay_flush(struct rchan *chan)
412{ 461{
413 unsigned int i; 462 unsigned int i;
463 struct rchan_buf *prev = NULL;
414 464
415 if (!chan) 465 if (!chan)
416 return; 466 return;
417 467
418 for (i = 0; i < NR_CPUS; i++) { 468 for (i = 0; i < NR_CPUS; i++) {
419 if (!chan->buf[i]) 469 if (!chan->buf[i] || chan->buf[i] == prev)
420 continue; 470 break;
421 relay_switch_subbuf(chan->buf[i], 0); 471 relay_switch_subbuf(chan->buf[i], 0);
472 prev = chan->buf[i];
422 } 473 }
423} 474}
424 475
diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h
index 703503fa22b6..0993d3e5753b 100644
--- a/fs/relayfs/relay.h
+++ b/fs/relayfs/relay.h
@@ -1,10 +1,6 @@
1#ifndef _RELAY_H 1#ifndef _RELAY_H
2#define _RELAY_H 2#define _RELAY_H
3 3
4struct dentry *relayfs_create_file(const char *name,
5 struct dentry *parent,
6 int mode,
7 struct rchan *chan);
8extern int relayfs_remove(struct dentry *dentry); 4extern int relayfs_remove(struct dentry *dentry);
9extern int relay_buf_empty(struct rchan_buf *buf); 5extern int relay_buf_empty(struct rchan_buf *buf);
10extern void relay_destroy_channel(struct kref *kref); 6extern void relay_destroy_channel(struct kref *kref);