Commit b86ff981a8252d83d6a7719ae09f3a05307e3592

Authored by Jens Axboe
1 parent b0e6e96299

[PATCH] relay: migrate from relayfs to a generic relay API

Original patch from Paul Mundt, sysfs parts removed by me since they
were broken.

Signed-off-by: Jens Axboe <axboe@suse.de>

Showing 12 changed files with 1212 additions and 1290 deletions Side-by-side Diff

... ... @@ -859,18 +859,6 @@
859 859 To compile this as a module, choose M here: the module will be called
860 860 ramfs.
861 861  
862   -config RELAYFS_FS
863   - tristate "Relayfs file system support"
864   - ---help---
865   - Relayfs is a high-speed data relay filesystem designed to provide
866   - an efficient mechanism for tools and facilities to relay large
867   - amounts of data from kernel space to user space.
868   -
869   - To compile this code as a module, choose M here: the module will be
870   - called relayfs.
871   -
872   - If unsure, say N.
873   -
874 862 config CONFIGFS_FS
875 863 tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)"
876 864 depends on EXPERIMENTAL
... ... @@ -91,7 +91,6 @@
91 91 obj-$(CONFIG_ADFS_FS) += adfs/
92 92 obj-$(CONFIG_FUSE_FS) += fuse/
93 93 obj-$(CONFIG_UDF_FS) += udf/
94   -obj-$(CONFIG_RELAYFS_FS) += relayfs/
95 94 obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
96 95 obj-$(CONFIG_JFS_FS) += jfs/
97 96 obj-$(CONFIG_XFS_FS) += xfs/
fs/relayfs/Makefile
1   -obj-$(CONFIG_RELAYFS_FS) += relayfs.o
2   -
3   -relayfs-y := relay.o inode.o buffers.o
fs/relayfs/buffers.c
1   -/*
2   - * RelayFS buffer management code.
3   - *
4   - * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
5   - * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
6   - *
7   - * This file is released under the GPL.
8   - */
9   -
10   -#include <linux/module.h>
11   -#include <linux/vmalloc.h>
12   -#include <linux/mm.h>
13   -#include <linux/relayfs_fs.h>
14   -#include "relay.h"
15   -#include "buffers.h"
16   -
17   -/*
18   - * close() vm_op implementation for relayfs file mapping.
19   - */
20   -static void relay_file_mmap_close(struct vm_area_struct *vma)
21   -{
22   - struct rchan_buf *buf = vma->vm_private_data;
23   - buf->chan->cb->buf_unmapped(buf, vma->vm_file);
24   -}
25   -
26   -/*
27   - * nopage() vm_op implementation for relayfs file mapping.
28   - */
29   -static struct page *relay_buf_nopage(struct vm_area_struct *vma,
30   - unsigned long address,
31   - int *type)
32   -{
33   - struct page *page;
34   - struct rchan_buf *buf = vma->vm_private_data;
35   - unsigned long offset = address - vma->vm_start;
36   -
37   - if (address > vma->vm_end)
38   - return NOPAGE_SIGBUS; /* Disallow mremap */
39   - if (!buf)
40   - return NOPAGE_OOM;
41   -
42   - page = vmalloc_to_page(buf->start + offset);
43   - if (!page)
44   - return NOPAGE_OOM;
45   - get_page(page);
46   -
47   - if (type)
48   - *type = VM_FAULT_MINOR;
49   -
50   - return page;
51   -}
52   -
53   -/*
54   - * vm_ops for relay file mappings.
55   - */
56   -static struct vm_operations_struct relay_file_mmap_ops = {
57   - .nopage = relay_buf_nopage,
58   - .close = relay_file_mmap_close,
59   -};
60   -
61   -/**
62   - * relay_mmap_buf: - mmap channel buffer to process address space
63   - * @buf: relay channel buffer
64   - * @vma: vm_area_struct describing memory to be mapped
65   - *
66   - * Returns 0 if ok, negative on error
67   - *
68   - * Caller should already have grabbed mmap_sem.
69   - */
70   -int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
71   -{
72   - unsigned long length = vma->vm_end - vma->vm_start;
73   - struct file *filp = vma->vm_file;
74   -
75   - if (!buf)
76   - return -EBADF;
77   -
78   - if (length != (unsigned long)buf->chan->alloc_size)
79   - return -EINVAL;
80   -
81   - vma->vm_ops = &relay_file_mmap_ops;
82   - vma->vm_private_data = buf;
83   - buf->chan->cb->buf_mapped(buf, filp);
84   -
85   - return 0;
86   -}
87   -
88   -/**
89   - * relay_alloc_buf - allocate a channel buffer
90   - * @buf: the buffer struct
91   - * @size: total size of the buffer
92   - *
93   - * Returns a pointer to the resulting buffer, NULL if unsuccessful
94   - */
95   -static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size)
96   -{
97   - void *mem;
98   - unsigned int i, j, n_pages;
99   -
100   - size = PAGE_ALIGN(size);
101   - n_pages = size >> PAGE_SHIFT;
102   -
103   - buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
104   - if (!buf->page_array)
105   - return NULL;
106   -
107   - for (i = 0; i < n_pages; i++) {
108   - buf->page_array[i] = alloc_page(GFP_KERNEL);
109   - if (unlikely(!buf->page_array[i]))
110   - goto depopulate;
111   - }
112   - mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL);
113   - if (!mem)
114   - goto depopulate;
115   -
116   - memset(mem, 0, size);
117   - buf->page_count = n_pages;
118   - return mem;
119   -
120   -depopulate:
121   - for (j = 0; j < i; j++)
122   - __free_page(buf->page_array[j]);
123   - kfree(buf->page_array);
124   - return NULL;
125   -}
126   -
127   -/**
128   - * relay_create_buf - allocate and initialize a channel buffer
129   - * @alloc_size: size of the buffer to allocate
130   - * @n_subbufs: number of sub-buffers in the channel
131   - *
132   - * Returns channel buffer if successful, NULL otherwise
133   - */
134   -struct rchan_buf *relay_create_buf(struct rchan *chan)
135   -{
136   - struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL);
137   - if (!buf)
138   - return NULL;
139   -
140   - buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
141   - if (!buf->padding)
142   - goto free_buf;
143   -
144   - buf->start = relay_alloc_buf(buf, chan->alloc_size);
145   - if (!buf->start)
146   - goto free_buf;
147   -
148   - buf->chan = chan;
149   - kref_get(&buf->chan->kref);
150   - return buf;
151   -
152   -free_buf:
153   - kfree(buf->padding);
154   - kfree(buf);
155   - return NULL;
156   -}
157   -
158   -/**
159   - * relay_destroy_buf - destroy an rchan_buf struct and associated buffer
160   - * @buf: the buffer struct
161   - */
162   -void relay_destroy_buf(struct rchan_buf *buf)
163   -{
164   - struct rchan *chan = buf->chan;
165   - unsigned int i;
166   -
167   - if (likely(buf->start)) {
168   - vunmap(buf->start);
169   - for (i = 0; i < buf->page_count; i++)
170   - __free_page(buf->page_array[i]);
171   - kfree(buf->page_array);
172   - }
173   - kfree(buf->padding);
174   - kfree(buf);
175   - kref_put(&chan->kref, relay_destroy_channel);
176   -}
177   -
178   -/**
179   - * relay_remove_buf - remove a channel buffer
180   - *
181   - * Removes the file from the relayfs fileystem, which also frees the
182   - * rchan_buf_struct and the channel buffer. Should only be called from
183   - * kref_put().
184   - */
185   -void relay_remove_buf(struct kref *kref)
186   -{
187   - struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
188   - buf->chan->cb->remove_buf_file(buf->dentry);
189   - relay_destroy_buf(buf);
190   -}
fs/relayfs/buffers.h
1   -#ifndef _BUFFERS_H
2   -#define _BUFFERS_H
3   -
4   -/* This inspired by rtai/shmem */
5   -#define FIX_SIZE(x) (((x) - 1) & PAGE_MASK) + PAGE_SIZE
6   -
7   -extern int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma);
8   -extern struct rchan_buf *relay_create_buf(struct rchan *chan);
9   -extern void relay_destroy_buf(struct rchan_buf *buf);
10   -extern void relay_remove_buf(struct kref *kref);
11   -
12   -#endif/* _BUFFERS_H */
fs/relayfs/inode.c
1   -/*
2   - * VFS-related code for RelayFS, a high-speed data relay filesystem.
3   - *
4   - * Copyright (C) 2003-2005 - Tom Zanussi <zanussi@us.ibm.com>, IBM Corp
5   - * Copyright (C) 2003-2005 - Karim Yaghmour <karim@opersys.com>
6   - *
7   - * Based on ramfs, Copyright (C) 2002 - Linus Torvalds
8   - *
9   - * This file is released under the GPL.
10   - */
11   -
12   -#include <linux/module.h>
13   -#include <linux/fs.h>
14   -#include <linux/mount.h>
15   -#include <linux/pagemap.h>
16   -#include <linux/init.h>
17   -#include <linux/string.h>
18   -#include <linux/backing-dev.h>
19   -#include <linux/namei.h>
20   -#include <linux/poll.h>
21   -#include <linux/relayfs_fs.h>
22   -#include "relay.h"
23   -#include "buffers.h"
24   -
25   -#define RELAYFS_MAGIC 0xF0B4A981
26   -
27   -static struct vfsmount * relayfs_mount;
28   -static int relayfs_mount_count;
29   -
30   -static struct backing_dev_info relayfs_backing_dev_info = {
31   - .ra_pages = 0, /* No readahead */
32   - .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
33   -};
34   -
35   -static struct inode *relayfs_get_inode(struct super_block *sb,
36   - int mode,
37   - struct file_operations *fops,
38   - void *data)
39   -{
40   - struct inode *inode;
41   -
42   - inode = new_inode(sb);
43   - if (!inode)
44   - return NULL;
45   -
46   - inode->i_mode = mode;
47   - inode->i_uid = 0;
48   - inode->i_gid = 0;
49   - inode->i_blksize = PAGE_CACHE_SIZE;
50   - inode->i_blocks = 0;
51   - inode->i_mapping->backing_dev_info = &relayfs_backing_dev_info;
52   - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
53   - switch (mode & S_IFMT) {
54   - case S_IFREG:
55   - inode->i_fop = fops;
56   - if (data)
57   - inode->u.generic_ip = data;
58   - break;
59   - case S_IFDIR:
60   - inode->i_op = &simple_dir_inode_operations;
61   - inode->i_fop = &simple_dir_operations;
62   -
63   - /* directory inodes start off with i_nlink == 2 (for "." entry) */
64   - inode->i_nlink++;
65   - break;
66   - default:
67   - break;
68   - }
69   -
70   - return inode;
71   -}
72   -
73   -/**
74   - * relayfs_create_entry - create a relayfs directory or file
75   - * @name: the name of the file to create
76   - * @parent: parent directory
77   - * @mode: mode
78   - * @fops: file operations to use for the file
79   - * @data: user-associated data for this file
80   - *
81   - * Returns the new dentry, NULL on failure
82   - *
83   - * Creates a file or directory with the specifed permissions.
84   - */
85   -static struct dentry *relayfs_create_entry(const char *name,
86   - struct dentry *parent,
87   - int mode,
88   - struct file_operations *fops,
89   - void *data)
90   -{
91   - struct dentry *d;
92   - struct inode *inode;
93   - int error = 0;
94   -
95   - BUG_ON(!name || !(S_ISREG(mode) || S_ISDIR(mode)));
96   -
97   - error = simple_pin_fs("relayfs", &relayfs_mount, &relayfs_mount_count);
98   - if (error) {
99   - printk(KERN_ERR "Couldn't mount relayfs: errcode %d\n", error);
100   - return NULL;
101   - }
102   -
103   - if (!parent && relayfs_mount && relayfs_mount->mnt_sb)
104   - parent = relayfs_mount->mnt_sb->s_root;
105   -
106   - if (!parent) {
107   - simple_release_fs(&relayfs_mount, &relayfs_mount_count);
108   - return NULL;
109   - }
110   -
111   - parent = dget(parent);
112   - mutex_lock(&parent->d_inode->i_mutex);
113   - d = lookup_one_len(name, parent, strlen(name));
114   - if (IS_ERR(d)) {
115   - d = NULL;
116   - goto release_mount;
117   - }
118   -
119   - if (d->d_inode) {
120   - d = NULL;
121   - goto release_mount;
122   - }
123   -
124   - inode = relayfs_get_inode(parent->d_inode->i_sb, mode, fops, data);
125   - if (!inode) {
126   - d = NULL;
127   - goto release_mount;
128   - }
129   -
130   - d_instantiate(d, inode);
131   - dget(d); /* Extra count - pin the dentry in core */
132   -
133   - if (S_ISDIR(mode))
134   - parent->d_inode->i_nlink++;
135   -
136   - goto exit;
137   -
138   -release_mount:
139   - simple_release_fs(&relayfs_mount, &relayfs_mount_count);
140   -
141   -exit:
142   - mutex_unlock(&parent->d_inode->i_mutex);
143   - dput(parent);
144   - return d;
145   -}
146   -
147   -/**
148   - * relayfs_create_file - create a file in the relay filesystem
149   - * @name: the name of the file to create
150   - * @parent: parent directory
151   - * @mode: mode, if not specied the default perms are used
152   - * @fops: file operations to use for the file
153   - * @data: user-associated data for this file
154   - *
155   - * Returns file dentry if successful, NULL otherwise.
156   - *
157   - * The file will be created user r on behalf of current user.
158   - */
159   -struct dentry *relayfs_create_file(const char *name,
160   - struct dentry *parent,
161   - int mode,
162   - struct file_operations *fops,
163   - void *data)
164   -{
165   - BUG_ON(!fops);
166   -
167   - if (!mode)
168   - mode = S_IRUSR;
169   - mode = (mode & S_IALLUGO) | S_IFREG;
170   -
171   - return relayfs_create_entry(name, parent, mode, fops, data);
172   -}
173   -
174   -/**
175   - * relayfs_create_dir - create a directory in the relay filesystem
176   - * @name: the name of the directory to create
177   - * @parent: parent directory, NULL if parent should be fs root
178   - *
179   - * Returns directory dentry if successful, NULL otherwise.
180   - *
181   - * The directory will be created world rwx on behalf of current user.
182   - */
183   -struct dentry *relayfs_create_dir(const char *name, struct dentry *parent)
184   -{
185   - int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
186   - return relayfs_create_entry(name, parent, mode, NULL, NULL);
187   -}
188   -
189   -/**
190   - * relayfs_remove - remove a file or directory in the relay filesystem
191   - * @dentry: file or directory dentry
192   - *
193   - * Returns 0 if successful, negative otherwise.
194   - */
195   -int relayfs_remove(struct dentry *dentry)
196   -{
197   - struct dentry *parent;
198   - int error = 0;
199   -
200   - if (!dentry)
201   - return -EINVAL;
202   - parent = dentry->d_parent;
203   - if (!parent)
204   - return -EINVAL;
205   -
206   - parent = dget(parent);
207   - mutex_lock(&parent->d_inode->i_mutex);
208   - if (dentry->d_inode) {
209   - if (S_ISDIR(dentry->d_inode->i_mode))
210   - error = simple_rmdir(parent->d_inode, dentry);
211   - else
212   - error = simple_unlink(parent->d_inode, dentry);
213   - if (!error)
214   - d_delete(dentry);
215   - }
216   - if (!error)
217   - dput(dentry);
218   - mutex_unlock(&parent->d_inode->i_mutex);
219   - dput(parent);
220   -
221   - if (!error)
222   - simple_release_fs(&relayfs_mount, &relayfs_mount_count);
223   -
224   - return error;
225   -}
226   -
227   -/**
228   - * relayfs_remove_file - remove a file from relay filesystem
229   - * @dentry: directory dentry
230   - *
231   - * Returns 0 if successful, negative otherwise.
232   - */
233   -int relayfs_remove_file(struct dentry *dentry)
234   -{
235   - return relayfs_remove(dentry);
236   -}
237   -
238   -/**
239   - * relayfs_remove_dir - remove a directory in the relay filesystem
240   - * @dentry: directory dentry
241   - *
242   - * Returns 0 if successful, negative otherwise.
243   - */
244   -int relayfs_remove_dir(struct dentry *dentry)
245   -{
246   - return relayfs_remove(dentry);
247   -}
248   -
249   -/**
250   - * relay_file_open - open file op for relay files
251   - * @inode: the inode
252   - * @filp: the file
253   - *
254   - * Increments the channel buffer refcount.
255   - */
256   -static int relay_file_open(struct inode *inode, struct file *filp)
257   -{
258   - struct rchan_buf *buf = inode->u.generic_ip;
259   - kref_get(&buf->kref);
260   - filp->private_data = buf;
261   -
262   - return 0;
263   -}
264   -
265   -/**
266   - * relay_file_mmap - mmap file op for relay files
267   - * @filp: the file
268   - * @vma: the vma describing what to map
269   - *
270   - * Calls upon relay_mmap_buf to map the file into user space.
271   - */
272   -static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma)
273   -{
274   - struct rchan_buf *buf = filp->private_data;
275   - return relay_mmap_buf(buf, vma);
276   -}
277   -
278   -/**
279   - * relay_file_poll - poll file op for relay files
280   - * @filp: the file
281   - * @wait: poll table
282   - *
283   - * Poll implemention.
284   - */
285   -static unsigned int relay_file_poll(struct file *filp, poll_table *wait)
286   -{
287   - unsigned int mask = 0;
288   - struct rchan_buf *buf = filp->private_data;
289   -
290   - if (buf->finalized)
291   - return POLLERR;
292   -
293   - if (filp->f_mode & FMODE_READ) {
294   - poll_wait(filp, &buf->read_wait, wait);
295   - if (!relay_buf_empty(buf))
296   - mask |= POLLIN | POLLRDNORM;
297   - }
298   -
299   - return mask;
300   -}
301   -
302   -/**
303   - * relay_file_release - release file op for relay files
304   - * @inode: the inode
305   - * @filp: the file
306   - *
307   - * Decrements the channel refcount, as the filesystem is
308   - * no longer using it.
309   - */
310   -static int relay_file_release(struct inode *inode, struct file *filp)
311   -{
312   - struct rchan_buf *buf = filp->private_data;
313   - kref_put(&buf->kref, relay_remove_buf);
314   -
315   - return 0;
316   -}
317   -
318   -/**
319   - * relay_file_read_consume - update the consumed count for the buffer
320   - */
321   -static void relay_file_read_consume(struct rchan_buf *buf,
322   - size_t read_pos,
323   - size_t bytes_consumed)
324   -{
325   - size_t subbuf_size = buf->chan->subbuf_size;
326   - size_t n_subbufs = buf->chan->n_subbufs;
327   - size_t read_subbuf;
328   -
329   - if (buf->bytes_consumed + bytes_consumed > subbuf_size) {
330   - relay_subbufs_consumed(buf->chan, buf->cpu, 1);
331   - buf->bytes_consumed = 0;
332   - }
333   -
334   - buf->bytes_consumed += bytes_consumed;
335   - read_subbuf = read_pos / buf->chan->subbuf_size;
336   - if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) {
337   - if ((read_subbuf == buf->subbufs_produced % n_subbufs) &&
338   - (buf->offset == subbuf_size))
339   - return;
340   - relay_subbufs_consumed(buf->chan, buf->cpu, 1);
341   - buf->bytes_consumed = 0;
342   - }
343   -}
344   -
345   -/**
346   - * relay_file_read_avail - boolean, are there unconsumed bytes available?
347   - */
348   -static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
349   -{
350   - size_t bytes_produced, bytes_consumed, write_offset;
351   - size_t subbuf_size = buf->chan->subbuf_size;
352   - size_t n_subbufs = buf->chan->n_subbufs;
353   - size_t produced = buf->subbufs_produced % n_subbufs;
354   - size_t consumed = buf->subbufs_consumed % n_subbufs;
355   -
356   - write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset;
357   -
358   - if (consumed > produced) {
359   - if ((produced > n_subbufs) &&
360   - (produced + n_subbufs - consumed <= n_subbufs))
361   - produced += n_subbufs;
362   - } else if (consumed == produced) {
363   - if (buf->offset > subbuf_size) {
364   - produced += n_subbufs;
365   - if (buf->subbufs_produced == buf->subbufs_consumed)
366   - consumed += n_subbufs;
367   - }
368   - }
369   -
370   - if (buf->offset > subbuf_size)
371   - bytes_produced = (produced - 1) * subbuf_size + write_offset;
372   - else
373   - bytes_produced = produced * subbuf_size + write_offset;
374   - bytes_consumed = consumed * subbuf_size + buf->bytes_consumed;
375   -
376   - if (bytes_produced == bytes_consumed)
377   - return 0;
378   -
379   - relay_file_read_consume(buf, read_pos, 0);
380   -
381   - return 1;
382   -}
383   -
384   -/**
385   - * relay_file_read_subbuf_avail - return bytes available in sub-buffer
386   - */
387   -static size_t relay_file_read_subbuf_avail(size_t read_pos,
388   - struct rchan_buf *buf)
389   -{
390   - size_t padding, avail = 0;
391   - size_t read_subbuf, read_offset, write_subbuf, write_offset;
392   - size_t subbuf_size = buf->chan->subbuf_size;
393   -
394   - write_subbuf = (buf->data - buf->start) / subbuf_size;
395   - write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset;
396   - read_subbuf = read_pos / subbuf_size;
397   - read_offset = read_pos % subbuf_size;
398   - padding = buf->padding[read_subbuf];
399   -
400   - if (read_subbuf == write_subbuf) {
401   - if (read_offset + padding < write_offset)
402   - avail = write_offset - (read_offset + padding);
403   - } else
404   - avail = (subbuf_size - padding) - read_offset;
405   -
406   - return avail;
407   -}
408   -
409   -/**
410   - * relay_file_read_start_pos - find the first available byte to read
411   - *
412   - * If the read_pos is in the middle of padding, return the
413   - * position of the first actually available byte, otherwise
414   - * return the original value.
415   - */
416   -static size_t relay_file_read_start_pos(size_t read_pos,
417   - struct rchan_buf *buf)
418   -{
419   - size_t read_subbuf, padding, padding_start, padding_end;
420   - size_t subbuf_size = buf->chan->subbuf_size;
421   - size_t n_subbufs = buf->chan->n_subbufs;
422   -
423   - read_subbuf = read_pos / subbuf_size;
424   - padding = buf->padding[read_subbuf];
425   - padding_start = (read_subbuf + 1) * subbuf_size - padding;
426   - padding_end = (read_subbuf + 1) * subbuf_size;
427   - if (read_pos >= padding_start && read_pos < padding_end) {
428   - read_subbuf = (read_subbuf + 1) % n_subbufs;
429   - read_pos = read_subbuf * subbuf_size;
430   - }
431   -
432   - return read_pos;
433   -}
434   -
435   -/**
436   - * relay_file_read_end_pos - return the new read position
437   - */
438   -static size_t relay_file_read_end_pos(struct rchan_buf *buf,
439   - size_t read_pos,
440   - size_t count)
441   -{
442   - size_t read_subbuf, padding, end_pos;
443   - size_t subbuf_size = buf->chan->subbuf_size;
444   - size_t n_subbufs = buf->chan->n_subbufs;
445   -
446   - read_subbuf = read_pos / subbuf_size;
447   - padding = buf->padding[read_subbuf];
448   - if (read_pos % subbuf_size + count + padding == subbuf_size)
449   - end_pos = (read_subbuf + 1) * subbuf_size;
450   - else
451   - end_pos = read_pos + count;
452   - if (end_pos >= subbuf_size * n_subbufs)
453   - end_pos = 0;
454   -
455   - return end_pos;
456   -}
457   -
458   -/**
459   - * relay_file_read - read file op for relay files
460   - * @filp: the file
461   - * @buffer: the userspace buffer
462   - * @count: number of bytes to read
463   - * @ppos: position to read from
464   - *
465   - * Reads count bytes or the number of bytes available in the
466   - * current sub-buffer being read, whichever is smaller.
467   - */
468   -static ssize_t relay_file_read(struct file *filp,
469   - char __user *buffer,
470   - size_t count,
471   - loff_t *ppos)
472   -{
473   - struct rchan_buf *buf = filp->private_data;
474   - struct inode *inode = filp->f_dentry->d_inode;
475   - size_t read_start, avail;
476   - ssize_t ret = 0;
477   - void *from;
478   -
479   - mutex_lock(&inode->i_mutex);
480   - if(!relay_file_read_avail(buf, *ppos))
481   - goto out;
482   -
483   - read_start = relay_file_read_start_pos(*ppos, buf);
484   - avail = relay_file_read_subbuf_avail(read_start, buf);
485   - if (!avail)
486   - goto out;
487   -
488   - from = buf->start + read_start;
489   - ret = count = min(count, avail);
490   - if (copy_to_user(buffer, from, count)) {
491   - ret = -EFAULT;
492   - goto out;
493   - }
494   - relay_file_read_consume(buf, read_start, count);
495   - *ppos = relay_file_read_end_pos(buf, read_start, count);
496   -out:
497   - mutex_unlock(&inode->i_mutex);
498   - return ret;
499   -}
500   -
501   -struct file_operations relay_file_operations = {
502   - .open = relay_file_open,
503   - .poll = relay_file_poll,
504   - .mmap = relay_file_mmap,
505   - .read = relay_file_read,
506   - .llseek = no_llseek,
507   - .release = relay_file_release,
508   -};
509   -
510   -static struct super_operations relayfs_ops = {
511   - .statfs = simple_statfs,
512   - .drop_inode = generic_delete_inode,
513   -};
514   -
515   -static int relayfs_fill_super(struct super_block * sb, void * data, int silent)
516   -{
517   - struct inode *inode;
518   - struct dentry *root;
519   - int mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
520   -
521   - sb->s_blocksize = PAGE_CACHE_SIZE;
522   - sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
523   - sb->s_magic = RELAYFS_MAGIC;
524   - sb->s_op = &relayfs_ops;
525   - inode = relayfs_get_inode(sb, mode, NULL, NULL);
526   -
527   - if (!inode)
528   - return -ENOMEM;
529   -
530   - root = d_alloc_root(inode);
531   - if (!root) {
532   - iput(inode);
533   - return -ENOMEM;
534   - }
535   - sb->s_root = root;
536   -
537   - return 0;
538   -}
539   -
540   -static struct super_block * relayfs_get_sb(struct file_system_type *fs_type,
541   - int flags, const char *dev_name,
542   - void *data)
543   -{
544   - return get_sb_single(fs_type, flags, data, relayfs_fill_super);
545   -}
546   -
547   -static struct file_system_type relayfs_fs_type = {
548   - .owner = THIS_MODULE,
549   - .name = "relayfs",
550   - .get_sb = relayfs_get_sb,
551   - .kill_sb = kill_litter_super,
552   -};
553   -
554   -static int __init init_relayfs_fs(void)
555   -{
556   - return register_filesystem(&relayfs_fs_type);
557   -}
558   -
559   -static void __exit exit_relayfs_fs(void)
560   -{
561   -
562   -
563   -
564   -
565   -
566   - unregister_filesystem(&relayfs_fs_type);
567   -}
568   -
569   -module_init(init_relayfs_fs)
570   -module_exit(exit_relayfs_fs)
571   -
572   -EXPORT_SYMBOL_GPL(relay_file_operations);
573   -EXPORT_SYMBOL_GPL(relayfs_create_dir);
574   -EXPORT_SYMBOL_GPL(relayfs_remove_dir);
575   -EXPORT_SYMBOL_GPL(relayfs_create_file);
576   -EXPORT_SYMBOL_GPL(relayfs_remove_file);
577   -
578   -MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>");
579   -MODULE_DESCRIPTION("Relay Filesystem");
580   -MODULE_LICENSE("GPL");
fs/relayfs/relay.c
1   -/*
2   - * Public API and common code for RelayFS.
3   - *
4   - * See Documentation/filesystems/relayfs.txt for an overview of relayfs.
5   - *
6   - * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
7   - * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
8   - *
9   - * This file is released under the GPL.
10   - */
11   -
12   -#include <linux/errno.h>
13   -#include <linux/stddef.h>
14   -#include <linux/slab.h>
15   -#include <linux/module.h>
16   -#include <linux/string.h>
17   -#include <linux/relayfs_fs.h>
18   -#include "relay.h"
19   -#include "buffers.h"
20   -
21   -/**
22   - * relay_buf_empty - boolean, is the channel buffer empty?
23   - * @buf: channel buffer
24   - *
25   - * Returns 1 if the buffer is empty, 0 otherwise.
26   - */
27   -int relay_buf_empty(struct rchan_buf *buf)
28   -{
29   - return (buf->subbufs_produced - buf->subbufs_consumed) ? 0 : 1;
30   -}
31   -
32   -/**
33   - * relay_buf_full - boolean, is the channel buffer full?
34   - * @buf: channel buffer
35   - *
36   - * Returns 1 if the buffer is full, 0 otherwise.
37   - */
38   -int relay_buf_full(struct rchan_buf *buf)
39   -{
40   - size_t ready = buf->subbufs_produced - buf->subbufs_consumed;
41   - return (ready >= buf->chan->n_subbufs) ? 1 : 0;
42   -}
43   -
44   -/*
45   - * High-level relayfs kernel API and associated functions.
46   - */
47   -
48   -/*
49   - * rchan_callback implementations defining default channel behavior. Used
50   - * in place of corresponding NULL values in client callback struct.
51   - */
52   -
53   -/*
54   - * subbuf_start() default callback. Does nothing.
55   - */
56   -static int subbuf_start_default_callback (struct rchan_buf *buf,
57   - void *subbuf,
58   - void *prev_subbuf,
59   - size_t prev_padding)
60   -{
61   - if (relay_buf_full(buf))
62   - return 0;
63   -
64   - return 1;
65   -}
66   -
67   -/*
68   - * buf_mapped() default callback. Does nothing.
69   - */
70   -static void buf_mapped_default_callback(struct rchan_buf *buf,
71   - struct file *filp)
72   -{
73   -}
74   -
75   -/*
76   - * buf_unmapped() default callback. Does nothing.
77   - */
78   -static void buf_unmapped_default_callback(struct rchan_buf *buf,
79   - struct file *filp)
80   -{
81   -}
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   -
104   -/* relay channel default callbacks */
105   -static struct rchan_callbacks default_channel_callbacks = {
106   - .subbuf_start = subbuf_start_default_callback,
107   - .buf_mapped = buf_mapped_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,
111   -};
112   -
113   -/**
114   - * wakeup_readers - wake up readers waiting on a channel
115   - * @private: the channel buffer
116   - *
117   - * This is the work function used to defer reader waking. The
118   - * reason waking is deferred is that calling directly from write
119   - * causes problems if you're writing from say the scheduler.
120   - */
121   -static void wakeup_readers(void *private)
122   -{
123   - struct rchan_buf *buf = private;
124   - wake_up_interruptible(&buf->read_wait);
125   -}
126   -
127   -/**
128   - * __relay_reset - reset a channel buffer
129   - * @buf: the channel buffer
130   - * @init: 1 if this is a first-time initialization
131   - *
132   - * See relay_reset for description of effect.
133   - */
134   -static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
135   -{
136   - size_t i;
137   -
138   - if (init) {
139   - init_waitqueue_head(&buf->read_wait);
140   - kref_init(&buf->kref);
141   - INIT_WORK(&buf->wake_readers, NULL, NULL);
142   - } else {
143   - cancel_delayed_work(&buf->wake_readers);
144   - flush_scheduled_work();
145   - }
146   -
147   - buf->subbufs_produced = 0;
148   - buf->subbufs_consumed = 0;
149   - buf->bytes_consumed = 0;
150   - buf->finalized = 0;
151   - buf->data = buf->start;
152   - buf->offset = 0;
153   -
154   - for (i = 0; i < buf->chan->n_subbufs; i++)
155   - buf->padding[i] = 0;
156   -
157   - buf->chan->cb->subbuf_start(buf, buf->data, NULL, 0);
158   -}
159   -
160   -/**
161   - * relay_reset - reset the channel
162   - * @chan: the channel
163   - *
164   - * This has the effect of erasing all data from all channel buffers
165   - * and restarting the channel in its initial state. The buffers
166   - * are not freed, so any mappings are still in effect.
167   - *
168   - * NOTE: Care should be taken that the channel isn't actually
169   - * being used by anything when this call is made.
170   - */
171   -void relay_reset(struct rchan *chan)
172   -{
173   - unsigned int i;
174   - struct rchan_buf *prev = NULL;
175   -
176   - if (!chan)
177   - return;
178   -
179   - for (i = 0; i < NR_CPUS; i++) {
180   - if (!chan->buf[i] || chan->buf[i] == prev)
181   - break;
182   - __relay_reset(chan->buf[i], 0);
183   - prev = chan->buf[i];
184   - }
185   -}
186   -
187   -/**
188   - * relay_open_buf - create a new channel buffer in relayfs
189   - *
190   - * Internal - used by relay_open().
191   - */
192   -static struct rchan_buf *relay_open_buf(struct rchan *chan,
193   - const char *filename,
194   - struct dentry *parent,
195   - int *is_global)
196   -{
197   - struct rchan_buf *buf;
198   - struct dentry *dentry;
199   -
200   - if (*is_global)
201   - return chan->buf[0];
202   -
203   - buf = relay_create_buf(chan);
204   - if (!buf)
205   - return NULL;
206   -
207   - /* Create file in fs */
208   - dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR,
209   - buf, is_global);
210   - if (!dentry) {
211   - relay_destroy_buf(buf);
212   - return NULL;
213   - }
214   -
215   - buf->dentry = dentry;
216   - __relay_reset(buf, 1);
217   -
218   - return buf;
219   -}
220   -
221   -/**
222   - * relay_close_buf - close a channel buffer
223   - * @buf: channel buffer
224   - *
225   - * Marks the buffer finalized and restores the default callbacks.
226   - * The channel buffer and channel buffer data structure are then freed
227   - * automatically when the last reference is given up.
228   - */
229   -static inline void relay_close_buf(struct rchan_buf *buf)
230   -{
231   - buf->finalized = 1;
232   - buf->chan->cb = &default_channel_callbacks;
233   - cancel_delayed_work(&buf->wake_readers);
234   - flush_scheduled_work();
235   - kref_put(&buf->kref, relay_remove_buf);
236   -}
237   -
238   -static inline void setup_callbacks(struct rchan *chan,
239   - struct rchan_callbacks *cb)
240   -{
241   - if (!cb) {
242   - chan->cb = &default_channel_callbacks;
243   - return;
244   - }
245   -
246   - if (!cb->subbuf_start)
247   - cb->subbuf_start = subbuf_start_default_callback;
248   - if (!cb->buf_mapped)
249   - cb->buf_mapped = buf_mapped_default_callback;
250   - if (!cb->buf_unmapped)
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;
256   - chan->cb = cb;
257   -}
258   -
259   -/**
260   - * relay_open - create a new relayfs channel
261   - * @base_filename: base name of files to create
262   - * @parent: dentry of parent directory, NULL for root directory
263   - * @subbuf_size: size of sub-buffers
264   - * @n_subbufs: number of sub-buffers
265   - * @cb: client callback functions
266   - *
267   - * Returns channel pointer if successful, NULL otherwise.
268   - *
269   - * Creates a channel buffer for each cpu using the sizes and
270   - * attributes specified. The created channel buffer files
271   - * will be named base_filename0...base_filenameN-1. File
272   - * permissions will be S_IRUSR.
273   - */
274   -struct rchan *relay_open(const char *base_filename,
275   - struct dentry *parent,
276   - size_t subbuf_size,
277   - size_t n_subbufs,
278   - struct rchan_callbacks *cb)
279   -{
280   - unsigned int i;
281   - struct rchan *chan;
282   - char *tmpname;
283   - int is_global = 0;
284   -
285   - if (!base_filename)
286   - return NULL;
287   -
288   - if (!(subbuf_size && n_subbufs))
289   - return NULL;
290   -
291   - chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL);
292   - if (!chan)
293   - return NULL;
294   -
295   - chan->version = RELAYFS_CHANNEL_VERSION;
296   - chan->n_subbufs = n_subbufs;
297   - chan->subbuf_size = subbuf_size;
298   - chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs);
299   - setup_callbacks(chan, cb);
300   - kref_init(&chan->kref);
301   -
302   - tmpname = kmalloc(NAME_MAX + 1, GFP_KERNEL);
303   - if (!tmpname)
304   - goto free_chan;
305   -
306   - for_each_online_cpu(i) {
307   - sprintf(tmpname, "%s%d", base_filename, i);
308   - chan->buf[i] = relay_open_buf(chan, tmpname, parent,
309   - &is_global);
310   - chan->buf[i]->cpu = i;
311   - if (!chan->buf[i])
312   - goto free_bufs;
313   - }
314   -
315   - kfree(tmpname);
316   - return chan;
317   -
318   -free_bufs:
319   - for (i = 0; i < NR_CPUS; i++) {
320   - if (!chan->buf[i])
321   - break;
322   - relay_close_buf(chan->buf[i]);
323   - if (is_global)
324   - break;
325   - }
326   - kfree(tmpname);
327   -
328   -free_chan:
329   - kref_put(&chan->kref, relay_destroy_channel);
330   - return NULL;
331   -}
332   -
333   -/**
334   - * relay_switch_subbuf - switch to a new sub-buffer
335   - * @buf: channel buffer
336   - * @length: size of current event
337   - *
338   - * Returns either the length passed in or 0 if full.
339   -
340   - * Performs sub-buffer-switch tasks such as invoking callbacks,
341   - * updating padding counts, waking up readers, etc.
342   - */
343   -size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
344   -{
345   - void *old, *new;
346   - size_t old_subbuf, new_subbuf;
347   -
348   - if (unlikely(length > buf->chan->subbuf_size))
349   - goto toobig;
350   -
351   - if (buf->offset != buf->chan->subbuf_size + 1) {
352   - buf->prev_padding = buf->chan->subbuf_size - buf->offset;
353   - old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
354   - buf->padding[old_subbuf] = buf->prev_padding;
355   - buf->subbufs_produced++;
356   - if (waitqueue_active(&buf->read_wait)) {
357   - PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf);
358   - schedule_delayed_work(&buf->wake_readers, 1);
359   - }
360   - }
361   -
362   - old = buf->data;
363   - new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
364   - new = buf->start + new_subbuf * buf->chan->subbuf_size;
365   - buf->offset = 0;
366   - if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) {
367   - buf->offset = buf->chan->subbuf_size + 1;
368   - return 0;
369   - }
370   - buf->data = new;
371   - buf->padding[new_subbuf] = 0;
372   -
373   - if (unlikely(length + buf->offset > buf->chan->subbuf_size))
374   - goto toobig;
375   -
376   - return length;
377   -
378   -toobig:
379   - buf->chan->last_toobig = length;
380   - return 0;
381   -}
382   -
383   -/**
384   - * relay_subbufs_consumed - update the buffer's sub-buffers-consumed count
385   - * @chan: the channel
386   - * @cpu: the cpu associated with the channel buffer to update
387   - * @subbufs_consumed: number of sub-buffers to add to current buf's count
388   - *
389   - * Adds to the channel buffer's consumed sub-buffer count.
390   - * subbufs_consumed should be the number of sub-buffers newly consumed,
391   - * not the total consumed.
392   - *
393   - * NOTE: kernel clients don't need to call this function if the channel
394   - * mode is 'overwrite'.
395   - */
396   -void relay_subbufs_consumed(struct rchan *chan,
397   - unsigned int cpu,
398   - size_t subbufs_consumed)
399   -{
400   - struct rchan_buf *buf;
401   -
402   - if (!chan)
403   - return;
404   -
405   - if (cpu >= NR_CPUS || !chan->buf[cpu])
406   - return;
407   -
408   - buf = chan->buf[cpu];
409   - buf->subbufs_consumed += subbufs_consumed;
410   - if (buf->subbufs_consumed > buf->subbufs_produced)
411   - buf->subbufs_consumed = buf->subbufs_produced;
412   -}
413   -
414   -/**
415   - * relay_destroy_channel - free the channel struct
416   - *
417   - * Should only be called from kref_put().
418   - */
419   -void relay_destroy_channel(struct kref *kref)
420   -{
421   - struct rchan *chan = container_of(kref, struct rchan, kref);
422   - kfree(chan);
423   -}
424   -
425   -/**
426   - * relay_close - close the channel
427   - * @chan: the channel
428   - *
429   - * Closes all channel buffers and frees the channel.
430   - */
431   -void relay_close(struct rchan *chan)
432   -{
433   - unsigned int i;
434   - struct rchan_buf *prev = NULL;
435   -
436   - if (!chan)
437   - return;
438   -
439   - for (i = 0; i < NR_CPUS; i++) {
440   - if (!chan->buf[i] || chan->buf[i] == prev)
441   - break;
442   - relay_close_buf(chan->buf[i]);
443   - prev = chan->buf[i];
444   - }
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   -
451   - kref_put(&chan->kref, relay_destroy_channel);
452   -}
453   -
454   -/**
455   - * relay_flush - close the channel
456   - * @chan: the channel
457   - *
458   - * Flushes all channel buffers i.e. forces buffer switch.
459   - */
460   -void relay_flush(struct rchan *chan)
461   -{
462   - unsigned int i;
463   - struct rchan_buf *prev = NULL;
464   -
465   - if (!chan)
466   - return;
467   -
468   - for (i = 0; i < NR_CPUS; i++) {
469   - if (!chan->buf[i] || chan->buf[i] == prev)
470   - break;
471   - relay_switch_subbuf(chan->buf[i], 0);
472   - prev = chan->buf[i];
473   - }
474   -}
475   -
476   -EXPORT_SYMBOL_GPL(relay_open);
477   -EXPORT_SYMBOL_GPL(relay_close);
478   -EXPORT_SYMBOL_GPL(relay_flush);
479   -EXPORT_SYMBOL_GPL(relay_reset);
480   -EXPORT_SYMBOL_GPL(relay_subbufs_consumed);
481   -EXPORT_SYMBOL_GPL(relay_switch_subbuf);
482   -EXPORT_SYMBOL_GPL(relay_buf_full);
fs/relayfs/relay.h
1   -#ifndef _RELAY_H
2   -#define _RELAY_H
3   -
4   -extern int relayfs_remove(struct dentry *dentry);
5   -extern int relay_buf_empty(struct rchan_buf *buf);
6   -extern void relay_destroy_channel(struct kref *kref);
7   -
8   -#endif /* _RELAY_H */
include/linux/relay.h
  1 +/*
  2 + * linux/include/linux/relay.h
  3 + *
  4 + * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
  5 + * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com)
  6 + *
  7 + * CONFIG_RELAY definitions and declarations
  8 + */
  9 +
  10 +#ifndef _LINUX_RELAY_H
  11 +#define _LINUX_RELAY_H
  12 +
  13 +#include <linux/config.h>
  14 +#include <linux/types.h>
  15 +#include <linux/sched.h>
  16 +#include <linux/wait.h>
  17 +#include <linux/list.h>
  18 +#include <linux/fs.h>
  19 +#include <linux/poll.h>
  20 +#include <linux/kref.h>
  21 +
  22 +/* Needs a _much_ better name... */
  23 +#define FIX_SIZE(x) ((((x) - 1) & PAGE_MASK) + PAGE_SIZE)
  24 +
  25 +/*
  26 + * Tracks changes to rchan/rchan_buf structs
  27 + */
  28 +#define RELAYFS_CHANNEL_VERSION 6
  29 +
  30 +/*
  31 + * Per-cpu relay channel buffer
  32 + */
  33 +struct rchan_buf
  34 +{
  35 + void *start; /* start of channel buffer */
  36 + void *data; /* start of current sub-buffer */
  37 + size_t offset; /* current offset into sub-buffer */
  38 + size_t subbufs_produced; /* count of sub-buffers produced */
  39 + size_t subbufs_consumed; /* count of sub-buffers consumed */
  40 + struct rchan *chan; /* associated channel */
  41 + wait_queue_head_t read_wait; /* reader wait queue */
  42 + struct work_struct wake_readers; /* reader wake-up work struct */
  43 + struct dentry *dentry; /* channel file dentry */
  44 + struct kref kref; /* channel buffer refcount */
  45 + struct page **page_array; /* array of current buffer pages */
  46 + unsigned int page_count; /* number of current buffer pages */
  47 + unsigned int finalized; /* buffer has been finalized */
  48 + size_t *padding; /* padding counts per sub-buffer */
  49 + size_t prev_padding; /* temporary variable */
  50 + size_t bytes_consumed; /* bytes consumed in cur read subbuf */
  51 + unsigned int cpu; /* this buf's cpu */
  52 +} ____cacheline_aligned;
  53 +
  54 +/*
  55 + * Relay channel data structure
  56 + */
  57 +struct rchan
  58 +{
  59 + u32 version; /* the version of this struct */
  60 + size_t subbuf_size; /* sub-buffer size */
  61 + size_t n_subbufs; /* number of sub-buffers per buffer */
  62 + size_t alloc_size; /* total buffer size allocated */
  63 + struct rchan_callbacks *cb; /* client callbacks */
  64 + struct kref kref; /* channel refcount */
  65 + void *private_data; /* for user-defined data */
  66 + size_t last_toobig; /* tried to log event > subbuf size */
  67 + struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */
  68 +};
  69 +
  70 +/*
  71 + * Relay channel client callbacks
  72 + */
  73 +struct rchan_callbacks
  74 +{
  75 + /*
  76 + * subbuf_start - called on buffer-switch to a new sub-buffer
  77 + * @buf: the channel buffer containing the new sub-buffer
  78 + * @subbuf: the start of the new sub-buffer
  79 + * @prev_subbuf: the start of the previous sub-buffer
  80 + * @prev_padding: unused space at the end of previous sub-buffer
  81 + *
  82 + * The client should return 1 to continue logging, 0 to stop
  83 + * logging.
  84 + *
  85 + * NOTE: subbuf_start will also be invoked when the buffer is
  86 + * created, so that the first sub-buffer can be initialized
  87 + * if necessary. In this case, prev_subbuf will be NULL.
  88 + *
  89 + * NOTE: the client can reserve bytes at the beginning of the new
  90 + * sub-buffer by calling subbuf_start_reserve() in this callback.
  91 + */
  92 + int (*subbuf_start) (struct rchan_buf *buf,
  93 + void *subbuf,
  94 + void *prev_subbuf,
  95 + size_t prev_padding);
  96 +
  97 + /*
  98 + * buf_mapped - relay buffer mmap notification
  99 + * @buf: the channel buffer
  100 + * @filp: relay file pointer
  101 + *
  102 + * Called when a relay file is successfully mmapped
  103 + */
  104 + void (*buf_mapped)(struct rchan_buf *buf,
  105 + struct file *filp);
  106 +
  107 + /*
  108 + * buf_unmapped - relay buffer unmap notification
  109 + * @buf: the channel buffer
  110 + * @filp: relay file pointer
  111 + *
  112 + * Called when a relay file is successfully unmapped
  113 + */
  114 + void (*buf_unmapped)(struct rchan_buf *buf,
  115 + struct file *filp);
  116 + /*
  117 + * create_buf_file - create file to represent a relay channel buffer
  118 + * @filename: the name of the file to create
  119 + * @parent: the parent of the file to create
  120 + * @mode: the mode of the file to create
  121 + * @buf: the channel buffer
  122 + * @is_global: outparam - set non-zero if the buffer should be global
  123 + *
  124 + * Called during relay_open(), once for each per-cpu buffer,
  125 + * to allow the client to create a file to be used to
  126 + * represent the corresponding channel buffer. If the file is
  127 + * created outside of relay, the parent must also exist in
  128 + * that filesystem.
  129 + *
  130 + * The callback should return the dentry of the file created
  131 + * to represent the relay buffer.
  132 + *
  133 + * Setting the is_global outparam to a non-zero value will
  134 + * cause relay_open() to create a single global buffer rather
  135 + * than the default set of per-cpu buffers.
  136 + *
  137 + * See Documentation/filesystems/relayfs.txt for more info.
  138 + */
  139 + struct dentry *(*create_buf_file)(const char *filename,
  140 + struct dentry *parent,
  141 + int mode,
  142 + struct rchan_buf *buf,
  143 + int *is_global);
  144 +
  145 + /*
  146 + * remove_buf_file - remove file representing a relay channel buffer
  147 + * @dentry: the dentry of the file to remove
  148 + *
  149 + * Called during relay_close(), once for each per-cpu buffer,
  150 + * to allow the client to remove a file used to represent a
  151 + * channel buffer.
  152 + *
  153 + * The callback should return 0 if successful, negative if not.
  154 + */
  155 + int (*remove_buf_file)(struct dentry *dentry);
  156 +};
  157 +
  158 +/*
  159 + * CONFIG_RELAY kernel API, kernel/relay.c
  160 + */
  161 +
  162 +struct rchan *relay_open(const char *base_filename,
  163 + struct dentry *parent,
  164 + size_t subbuf_size,
  165 + size_t n_subbufs,
  166 + struct rchan_callbacks *cb);
  167 +extern void relay_close(struct rchan *chan);
  168 +extern void relay_flush(struct rchan *chan);
  169 +extern void relay_subbufs_consumed(struct rchan *chan,
  170 + unsigned int cpu,
  171 + size_t consumed);
  172 +extern void relay_reset(struct rchan *chan);
  173 +extern int relay_buf_full(struct rchan_buf *buf);
  174 +
  175 +extern size_t relay_switch_subbuf(struct rchan_buf *buf,
  176 + size_t length);
  177 +
  178 +/**
  179 + * relay_write - write data into the channel
  180 + * @chan: relay channel
  181 + * @data: data to be written
  182 + * @length: number of bytes to write
  183 + *
  184 + * Writes data into the current cpu's channel buffer.
  185 + *
  186 + * Protects the buffer by disabling interrupts. Use this
  187 + * if you might be logging from interrupt context. Try
  188 + * __relay_write() if you know you won't be logging from
  189 + * interrupt context.
  190 + */
  191 +static inline void relay_write(struct rchan *chan,
  192 + const void *data,
  193 + size_t length)
  194 +{
  195 + unsigned long flags;
  196 + struct rchan_buf *buf;
  197 +
  198 + local_irq_save(flags);
  199 + buf = chan->buf[smp_processor_id()];
  200 + if (unlikely(buf->offset + length > chan->subbuf_size))
  201 + length = relay_switch_subbuf(buf, length);
  202 + memcpy(buf->data + buf->offset, data, length);
  203 + buf->offset += length;
  204 + local_irq_restore(flags);
  205 +}
  206 +
  207 +/**
  208 + * __relay_write - write data into the channel
  209 + * @chan: relay channel
  210 + * @data: data to be written
  211 + * @length: number of bytes to write
  212 + *
  213 + * Writes data into the current cpu's channel buffer.
  214 + *
  215 + * Protects the buffer by disabling preemption. Use
  216 + * relay_write() if you might be logging from interrupt
  217 + * context.
  218 + */
  219 +static inline void __relay_write(struct rchan *chan,
  220 + const void *data,
  221 + size_t length)
  222 +{
  223 + struct rchan_buf *buf;
  224 +
  225 + buf = chan->buf[get_cpu()];
  226 + if (unlikely(buf->offset + length > buf->chan->subbuf_size))
  227 + length = relay_switch_subbuf(buf, length);
  228 + memcpy(buf->data + buf->offset, data, length);
  229 + buf->offset += length;
  230 + put_cpu();
  231 +}
  232 +
  233 +/**
  234 + * relay_reserve - reserve slot in channel buffer
  235 + * @chan: relay channel
  236 + * @length: number of bytes to reserve
  237 + *
  238 + * Returns pointer to reserved slot, NULL if full.
  239 + *
  240 + * Reserves a slot in the current cpu's channel buffer.
  241 + * Does not protect the buffer at all - caller must provide
  242 + * appropriate synchronization.
  243 + */
  244 +static inline void *relay_reserve(struct rchan *chan, size_t length)
  245 +{
  246 + void *reserved;
  247 + struct rchan_buf *buf = chan->buf[smp_processor_id()];
  248 +
  249 + if (unlikely(buf->offset + length > buf->chan->subbuf_size)) {
  250 + length = relay_switch_subbuf(buf, length);
  251 + if (!length)
  252 + return NULL;
  253 + }
  254 + reserved = buf->data + buf->offset;
  255 + buf->offset += length;
  256 +
  257 + return reserved;
  258 +}
  259 +
  260 +/**
  261 + * subbuf_start_reserve - reserve bytes at the start of a sub-buffer
  262 + * @buf: relay channel buffer
  263 + * @length: number of bytes to reserve
  264 + *
  265 + * Helper function used to reserve bytes at the beginning of
  266 + * a sub-buffer in the subbuf_start() callback.
  267 + */
  268 +static inline void subbuf_start_reserve(struct rchan_buf *buf,
  269 + size_t length)
  270 +{
  271 + BUG_ON(length >= buf->chan->subbuf_size - 1);
  272 + buf->offset = length;
  273 +}
  274 +
  275 +/*
  276 + * exported relay file operations, kernel/relay.c
  277 + */
  278 +extern struct file_operations relay_file_operations;
  279 +
  280 +#endif /* _LINUX_RELAY_H */
... ... @@ -214,6 +214,17 @@
214 214  
215 215 Say N if unsure.
216 216  
  217 +config RELAY
  218 + bool "Kernel->user space relay support (formerly relayfs)"
  219 + help
  220 + This option enables support for relay interface support in
  221 + certain file systems (such as debugfs).
  222 + It is designed to provide an efficient mechanism for tools and
  223 + facilities to relay large amounts of data from kernel space to
  224 + user space.
  225 +
  226 + If unsure, say N.
  227 +
217 228 source "usr/Kconfig"
218 229  
219 230 config UID16
... ... @@ -34,6 +34,7 @@
34 34 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
35 35 obj-$(CONFIG_SECCOMP) += seccomp.o
36 36 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
  37 +obj-$(CONFIG_RELAY) += relay.o
37 38  
38 39 ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
39 40 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
  1 +/*
  2 + * Public API and common code for kernel->userspace relay file support.
  3 + *
  4 + * See Documentation/filesystems/relayfs.txt for an overview of relayfs.
  5 + *
  6 + * Copyright (C) 2002-2005 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
  7 + * Copyright (C) 1999-2005 - Karim Yaghmour (karim@opersys.com)
  8 + *
  9 + * Moved to kernel/relay.c by Paul Mundt, 2006.
  10 + *
  11 + * This file is released under the GPL.
  12 + */
  13 +#include <linux/errno.h>
  14 +#include <linux/stddef.h>
  15 +#include <linux/slab.h>
  16 +#include <linux/module.h>
  17 +#include <linux/string.h>
  18 +#include <linux/relay.h>
  19 +#include <linux/vmalloc.h>
  20 +#include <linux/mm.h>
  21 +
  22 +/*
  23 + * close() vm_op implementation for relay file mapping.
  24 + */
  25 +static void relay_file_mmap_close(struct vm_area_struct *vma)
  26 +{
  27 + struct rchan_buf *buf = vma->vm_private_data;
  28 + buf->chan->cb->buf_unmapped(buf, vma->vm_file);
  29 +}
  30 +
  31 +/*
  32 + * nopage() vm_op implementation for relay file mapping.
  33 + */
  34 +static struct page *relay_buf_nopage(struct vm_area_struct *vma,
  35 + unsigned long address,
  36 + int *type)
  37 +{
  38 + struct page *page;
  39 + struct rchan_buf *buf = vma->vm_private_data;
  40 + unsigned long offset = address - vma->vm_start;
  41 +
  42 + if (address > vma->vm_end)
  43 + return NOPAGE_SIGBUS; /* Disallow mremap */
  44 + if (!buf)
  45 + return NOPAGE_OOM;
  46 +
  47 + page = vmalloc_to_page(buf->start + offset);
  48 + if (!page)
  49 + return NOPAGE_OOM;
  50 + get_page(page);
  51 +
  52 + if (type)
  53 + *type = VM_FAULT_MINOR;
  54 +
  55 + return page;
  56 +}
  57 +
  58 +/*
  59 + * vm_ops for relay file mappings.
  60 + */
  61 +static struct vm_operations_struct relay_file_mmap_ops = {
  62 + .nopage = relay_buf_nopage,
  63 + .close = relay_file_mmap_close,
  64 +};
  65 +
  66 +/**
  67 + * relay_mmap_buf: - mmap channel buffer to process address space
  68 + * @buf: relay channel buffer
  69 + * @vma: vm_area_struct describing memory to be mapped
  70 + *
  71 + * Returns 0 if ok, negative on error
  72 + *
  73 + * Caller should already have grabbed mmap_sem.
  74 + */
  75 +int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
  76 +{
  77 + unsigned long length = vma->vm_end - vma->vm_start;
  78 + struct file *filp = vma->vm_file;
  79 +
  80 + if (!buf)
  81 + return -EBADF;
  82 +
  83 + if (length != (unsigned long)buf->chan->alloc_size)
  84 + return -EINVAL;
  85 +
  86 + vma->vm_ops = &relay_file_mmap_ops;
  87 + vma->vm_private_data = buf;
  88 + buf->chan->cb->buf_mapped(buf, filp);
  89 +
  90 + return 0;
  91 +}
  92 +
  93 +/**
  94 + * relay_alloc_buf - allocate a channel buffer
  95 + * @buf: the buffer struct
  96 + * @size: total size of the buffer
  97 + *
  98 + * Returns a pointer to the resulting buffer, NULL if unsuccessful
  99 + */
  100 +static void *relay_alloc_buf(struct rchan_buf *buf, unsigned long size)
  101 +{
  102 + void *mem;
  103 + unsigned int i, j, n_pages;
  104 +
  105 + size = PAGE_ALIGN(size);
  106 + n_pages = size >> PAGE_SHIFT;
  107 +
  108 + buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL);
  109 + if (!buf->page_array)
  110 + return NULL;
  111 +
  112 + for (i = 0; i < n_pages; i++) {
  113 + buf->page_array[i] = alloc_page(GFP_KERNEL);
  114 + if (unlikely(!buf->page_array[i]))
  115 + goto depopulate;
  116 + }
  117 + mem = vmap(buf->page_array, n_pages, VM_MAP, PAGE_KERNEL);
  118 + if (!mem)
  119 + goto depopulate;
  120 +
  121 + memset(mem, 0, size);
  122 + buf->page_count = n_pages;
  123 + return mem;
  124 +
  125 +depopulate:
  126 + for (j = 0; j < i; j++)
  127 + __free_page(buf->page_array[j]);
  128 + kfree(buf->page_array);
  129 + return NULL;
  130 +}
  131 +
  132 +/**
  133 + * relay_create_buf - allocate and initialize a channel buffer
  134 + * @alloc_size: size of the buffer to allocate
  135 + * @n_subbufs: number of sub-buffers in the channel
  136 + *
  137 + * Returns channel buffer if successful, NULL otherwise
  138 + */
  139 +struct rchan_buf *relay_create_buf(struct rchan *chan)
  140 +{
  141 + struct rchan_buf *buf = kcalloc(1, sizeof(struct rchan_buf), GFP_KERNEL);
  142 + if (!buf)
  143 + return NULL;
  144 +
  145 + buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
  146 + if (!buf->padding)
  147 + goto free_buf;
  148 +
  149 + buf->start = relay_alloc_buf(buf, chan->alloc_size);
  150 + if (!buf->start)
  151 + goto free_buf;
  152 +
  153 + buf->chan = chan;
  154 + kref_get(&buf->chan->kref);
  155 + return buf;
  156 +
  157 +free_buf:
  158 + kfree(buf->padding);
  159 + kfree(buf);
  160 + return NULL;
  161 +}
  162 +
  163 +/**
  164 + * relay_destroy_channel - free the channel struct
  165 + *
  166 + * Should only be called from kref_put().
  167 + */
  168 +void relay_destroy_channel(struct kref *kref)
  169 +{
  170 + struct rchan *chan = container_of(kref, struct rchan, kref);
  171 + kfree(chan);
  172 +}
  173 +
  174 +/**
  175 + * relay_destroy_buf - destroy an rchan_buf struct and associated buffer
  176 + * @buf: the buffer struct
  177 + */
  178 +void relay_destroy_buf(struct rchan_buf *buf)
  179 +{
  180 + struct rchan *chan = buf->chan;
  181 + unsigned int i;
  182 +
  183 + if (likely(buf->start)) {
  184 + vunmap(buf->start);
  185 + for (i = 0; i < buf->page_count; i++)
  186 + __free_page(buf->page_array[i]);
  187 + kfree(buf->page_array);
  188 + }
  189 + kfree(buf->padding);
  190 + kfree(buf);
  191 + kref_put(&chan->kref, relay_destroy_channel);
  192 +}
  193 +
  194 +/**
  195 + * relay_remove_buf - remove a channel buffer
  196 + *
  197 + * Removes the file from the fileystem, which also frees the
  198 + * rchan_buf_struct and the channel buffer. Should only be called from
  199 + * kref_put().
  200 + */
  201 +void relay_remove_buf(struct kref *kref)
  202 +{
  203 + struct rchan_buf *buf = container_of(kref, struct rchan_buf, kref);
  204 + buf->chan->cb->remove_buf_file(buf->dentry);
  205 + relay_destroy_buf(buf);
  206 +}
  207 +
  208 +/**
  209 + * relay_buf_empty - boolean, is the channel buffer empty?
  210 + * @buf: channel buffer
  211 + *
  212 + * Returns 1 if the buffer is empty, 0 otherwise.
  213 + */
  214 +int relay_buf_empty(struct rchan_buf *buf)
  215 +{
  216 + return (buf->subbufs_produced - buf->subbufs_consumed) ? 0 : 1;
  217 +}
  218 +EXPORT_SYMBOL_GPL(relay_buf_empty);
  219 +
  220 +/**
  221 + * relay_buf_full - boolean, is the channel buffer full?
  222 + * @buf: channel buffer
  223 + *
  224 + * Returns 1 if the buffer is full, 0 otherwise.
  225 + */
  226 +int relay_buf_full(struct rchan_buf *buf)
  227 +{
  228 + size_t ready = buf->subbufs_produced - buf->subbufs_consumed;
  229 + return (ready >= buf->chan->n_subbufs) ? 1 : 0;
  230 +}
  231 +EXPORT_SYMBOL_GPL(relay_buf_full);
  232 +
  233 +/*
  234 + * High-level relay kernel API and associated functions.
  235 + */
  236 +
  237 +/*
  238 + * rchan_callback implementations defining default channel behavior. Used
  239 + * in place of corresponding NULL values in client callback struct.
  240 + */
  241 +
  242 +/*
  243 + * subbuf_start() default callback. Does nothing.
  244 + */
  245 +static int subbuf_start_default_callback (struct rchan_buf *buf,
  246 + void *subbuf,
  247 + void *prev_subbuf,
  248 + size_t prev_padding)
  249 +{
  250 + if (relay_buf_full(buf))
  251 + return 0;
  252 +
  253 + return 1;
  254 +}
  255 +
  256 +/*
  257 + * buf_mapped() default callback. Does nothing.
  258 + */
  259 +static void buf_mapped_default_callback(struct rchan_buf *buf,
  260 + struct file *filp)
  261 +{
  262 +}
  263 +
  264 +/*
  265 + * buf_unmapped() default callback. Does nothing.
  266 + */
  267 +static void buf_unmapped_default_callback(struct rchan_buf *buf,
  268 + struct file *filp)
  269 +{
  270 +}
  271 +
  272 +/*
  273 + * create_buf_file_create() default callback. Does nothing.
  274 + */
  275 +static struct dentry *create_buf_file_default_callback(const char *filename,
  276 + struct dentry *parent,
  277 + int mode,
  278 + struct rchan_buf *buf,
  279 + int *is_global)
  280 +{
  281 + return NULL;
  282 +}
  283 +
  284 +/*
  285 + * remove_buf_file() default callback. Does nothing.
  286 + */
  287 +static int remove_buf_file_default_callback(struct dentry *dentry)
  288 +{
  289 + return -EINVAL;
  290 +}
  291 +
  292 +/* relay channel default callbacks */
  293 +static struct rchan_callbacks default_channel_callbacks = {
  294 + .subbuf_start = subbuf_start_default_callback,
  295 + .buf_mapped = buf_mapped_default_callback,
  296 + .buf_unmapped = buf_unmapped_default_callback,
  297 + .create_buf_file = create_buf_file_default_callback,
  298 + .remove_buf_file = remove_buf_file_default_callback,
  299 +};
  300 +
  301 +/**
  302 + * wakeup_readers - wake up readers waiting on a channel
  303 + * @private: the channel buffer
  304 + *
  305 + * This is the work function used to defer reader waking. The
  306 + * reason waking is deferred is that calling directly from write
  307 + * causes problems if you're writing from say the scheduler.
  308 + */
  309 +static void wakeup_readers(void *private)
  310 +{
  311 + struct rchan_buf *buf = private;
  312 + wake_up_interruptible(&buf->read_wait);
  313 +}
  314 +
  315 +/**
  316 + * __relay_reset - reset a channel buffer
  317 + * @buf: the channel buffer
  318 + * @init: 1 if this is a first-time initialization
  319 + *
  320 + * See relay_reset for description of effect.
  321 + */
  322 +static inline void __relay_reset(struct rchan_buf *buf, unsigned int init)
  323 +{
  324 + size_t i;
  325 +
  326 + if (init) {
  327 + init_waitqueue_head(&buf->read_wait);
  328 + kref_init(&buf->kref);
  329 + INIT_WORK(&buf->wake_readers, NULL, NULL);
  330 + } else {
  331 + cancel_delayed_work(&buf->wake_readers);
  332 + flush_scheduled_work();
  333 + }
  334 +
  335 + buf->subbufs_produced = 0;
  336 + buf->subbufs_consumed = 0;
  337 + buf->bytes_consumed = 0;
  338 + buf->finalized = 0;
  339 + buf->data = buf->start;
  340 + buf->offset = 0;
  341 +
  342 + for (i = 0; i < buf->chan->n_subbufs; i++)
  343 + buf->padding[i] = 0;
  344 +
  345 + buf->chan->cb->subbuf_start(buf, buf->data, NULL, 0);
  346 +}
  347 +
  348 +/**
  349 + * relay_reset - reset the channel
  350 + * @chan: the channel
  351 + *
  352 + * This has the effect of erasing all data from all channel buffers
  353 + * and restarting the channel in its initial state. The buffers
  354 + * are not freed, so any mappings are still in effect.
  355 + *
  356 + * NOTE: Care should be taken that the channel isn't actually
  357 + * being used by anything when this call is made.
  358 + */
  359 +void relay_reset(struct rchan *chan)
  360 +{
  361 + unsigned int i;
  362 + struct rchan_buf *prev = NULL;
  363 +
  364 + if (!chan)
  365 + return;
  366 +
  367 + for (i = 0; i < NR_CPUS; i++) {
  368 + if (!chan->buf[i] || chan->buf[i] == prev)
  369 + break;
  370 + __relay_reset(chan->buf[i], 0);
  371 + prev = chan->buf[i];
  372 + }
  373 +}
  374 +EXPORT_SYMBOL_GPL(relay_reset);
  375 +
  376 +/**
  377 + * relay_open_buf - create a new relay channel buffer
  378 + *
  379 + * Internal - used by relay_open().
  380 + */
  381 +static struct rchan_buf *relay_open_buf(struct rchan *chan,
  382 + const char *filename,
  383 + struct dentry *parent,
  384 + int *is_global)
  385 +{
  386 + struct rchan_buf *buf;
  387 + struct dentry *dentry;
  388 +
  389 + if (*is_global)
  390 + return chan->buf[0];
  391 +
  392 + buf = relay_create_buf(chan);
  393 + if (!buf)
  394 + return NULL;
  395 +
  396 + /* Create file in fs */
  397 + dentry = chan->cb->create_buf_file(filename, parent, S_IRUSR,
  398 + buf, is_global);
  399 + if (!dentry) {
  400 + relay_destroy_buf(buf);
  401 + return NULL;
  402 + }
  403 +
  404 + buf->dentry = dentry;
  405 + __relay_reset(buf, 1);
  406 +
  407 + return buf;
  408 +}
  409 +
  410 +/**
  411 + * relay_close_buf - close a channel buffer
  412 + * @buf: channel buffer
  413 + *
  414 + * Marks the buffer finalized and restores the default callbacks.
  415 + * The channel buffer and channel buffer data structure are then freed
  416 + * automatically when the last reference is given up.
  417 + */
  418 +static inline void relay_close_buf(struct rchan_buf *buf)
  419 +{
  420 + buf->finalized = 1;
  421 + cancel_delayed_work(&buf->wake_readers);
  422 + flush_scheduled_work();
  423 + kref_put(&buf->kref, relay_remove_buf);
  424 +}
  425 +
  426 +static inline void setup_callbacks(struct rchan *chan,
  427 + struct rchan_callbacks *cb)
  428 +{
  429 + if (!cb) {
  430 + chan->cb = &default_channel_callbacks;
  431 + return;
  432 + }
  433 +
  434 + if (!cb->subbuf_start)
  435 + cb->subbuf_start = subbuf_start_default_callback;
  436 + if (!cb->buf_mapped)
  437 + cb->buf_mapped = buf_mapped_default_callback;
  438 + if (!cb->buf_unmapped)
  439 + cb->buf_unmapped = buf_unmapped_default_callback;
  440 + if (!cb->create_buf_file)
  441 + cb->create_buf_file = create_buf_file_default_callback;
  442 + if (!cb->remove_buf_file)
  443 + cb->remove_buf_file = remove_buf_file_default_callback;
  444 + chan->cb = cb;
  445 +}
  446 +
  447 +/**
  448 + * relay_open - create a new relay channel
  449 + * @base_filename: base name of files to create
  450 + * @parent: dentry of parent directory, NULL for root directory
  451 + * @subbuf_size: size of sub-buffers
  452 + * @n_subbufs: number of sub-buffers
  453 + * @cb: client callback functions
  454 + *
  455 + * Returns channel pointer if successful, NULL otherwise.
  456 + *
  457 + * Creates a channel buffer for each cpu using the sizes and
  458 + * attributes specified. The created channel buffer files
  459 + * will be named base_filename0...base_filenameN-1. File
  460 + * permissions will be S_IRUSR.
  461 + */
  462 +struct rchan *relay_open(const char *base_filename,
  463 + struct dentry *parent,
  464 + size_t subbuf_size,
  465 + size_t n_subbufs,
  466 + struct rchan_callbacks *cb)
  467 +{
  468 + unsigned int i;
  469 + struct rchan *chan;
  470 + char *tmpname;
  471 + int is_global = 0;
  472 +
  473 + if (!base_filename)
  474 + return NULL;
  475 +
  476 + if (!(subbuf_size && n_subbufs))
  477 + return NULL;
  478 +
  479 + chan = kcalloc(1, sizeof(struct rchan), GFP_KERNEL);
  480 + if (!chan)
  481 + return NULL;
  482 +
  483 + chan->version = RELAYFS_CHANNEL_VERSION;
  484 + chan->n_subbufs = n_subbufs;
  485 + chan->subbuf_size = subbuf_size;
  486 + chan->alloc_size = FIX_SIZE(subbuf_size * n_subbufs);
  487 + setup_callbacks(chan, cb);
  488 + kref_init(&chan->kref);
  489 +
  490 + tmpname = kmalloc(NAME_MAX + 1, GFP_KERNEL);
  491 + if (!tmpname)
  492 + goto free_chan;
  493 +
  494 + for_each_online_cpu(i) {
  495 + sprintf(tmpname, "%s%d", base_filename, i);
  496 + chan->buf[i] = relay_open_buf(chan, tmpname, parent,
  497 + &is_global);
  498 + if (!chan->buf[i])
  499 + goto free_bufs;
  500 +
  501 + chan->buf[i]->cpu = i;
  502 + }
  503 +
  504 + kfree(tmpname);
  505 + return chan;
  506 +
  507 +free_bufs:
  508 + for (i = 0; i < NR_CPUS; i++) {
  509 + if (!chan->buf[i])
  510 + break;
  511 + relay_close_buf(chan->buf[i]);
  512 + if (is_global)
  513 + break;
  514 + }
  515 + kfree(tmpname);
  516 +
  517 +free_chan:
  518 + kref_put(&chan->kref, relay_destroy_channel);
  519 + return NULL;
  520 +}
  521 +EXPORT_SYMBOL_GPL(relay_open);
  522 +
  523 +/**
  524 + * relay_switch_subbuf - switch to a new sub-buffer
  525 + * @buf: channel buffer
  526 + * @length: size of current event
  527 + *
  528 + * Returns either the length passed in or 0 if full.
  529 + *
  530 + * Performs sub-buffer-switch tasks such as invoking callbacks,
  531 + * updating padding counts, waking up readers, etc.
  532 + */
  533 +size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
  534 +{
  535 + void *old, *new;
  536 + size_t old_subbuf, new_subbuf;
  537 +
  538 + if (unlikely(length > buf->chan->subbuf_size))
  539 + goto toobig;
  540 +
  541 + if (buf->offset != buf->chan->subbuf_size + 1) {
  542 + buf->prev_padding = buf->chan->subbuf_size - buf->offset;
  543 + old_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
  544 + buf->padding[old_subbuf] = buf->prev_padding;
  545 + buf->subbufs_produced++;
  546 + if (waitqueue_active(&buf->read_wait)) {
  547 + PREPARE_WORK(&buf->wake_readers, wakeup_readers, buf);
  548 + schedule_delayed_work(&buf->wake_readers, 1);
  549 + }
  550 + }
  551 +
  552 + old = buf->data;
  553 + new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
  554 + new = buf->start + new_subbuf * buf->chan->subbuf_size;
  555 + buf->offset = 0;
  556 + if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) {
  557 + buf->offset = buf->chan->subbuf_size + 1;
  558 + return 0;
  559 + }
  560 + buf->data = new;
  561 + buf->padding[new_subbuf] = 0;
  562 +
  563 + if (unlikely(length + buf->offset > buf->chan->subbuf_size))
  564 + goto toobig;
  565 +
  566 + return length;
  567 +
  568 +toobig:
  569 + buf->chan->last_toobig = length;
  570 + return 0;
  571 +}
  572 +EXPORT_SYMBOL_GPL(relay_switch_subbuf);
  573 +
  574 +/**
  575 + * relay_subbufs_consumed - update the buffer's sub-buffers-consumed count
  576 + * @chan: the channel
  577 + * @cpu: the cpu associated with the channel buffer to update
  578 + * @subbufs_consumed: number of sub-buffers to add to current buf's count
  579 + *
  580 + * Adds to the channel buffer's consumed sub-buffer count.
  581 + * subbufs_consumed should be the number of sub-buffers newly consumed,
  582 + * not the total consumed.
  583 + *
  584 + * NOTE: kernel clients don't need to call this function if the channel
  585 + * mode is 'overwrite'.
  586 + */
  587 +void relay_subbufs_consumed(struct rchan *chan,
  588 + unsigned int cpu,
  589 + size_t subbufs_consumed)
  590 +{
  591 + struct rchan_buf *buf;
  592 +
  593 + if (!chan)
  594 + return;
  595 +
  596 + if (cpu >= NR_CPUS || !chan->buf[cpu])
  597 + return;
  598 +
  599 + buf = chan->buf[cpu];
  600 + buf->subbufs_consumed += subbufs_consumed;
  601 + if (buf->subbufs_consumed > buf->subbufs_produced)
  602 + buf->subbufs_consumed = buf->subbufs_produced;
  603 +}
  604 +EXPORT_SYMBOL_GPL(relay_subbufs_consumed);
  605 +
  606 +/**
  607 + * relay_close - close the channel
  608 + * @chan: the channel
  609 + *
  610 + * Closes all channel buffers and frees the channel.
  611 + */
  612 +void relay_close(struct rchan *chan)
  613 +{
  614 + unsigned int i;
  615 + struct rchan_buf *prev = NULL;
  616 +
  617 + if (!chan)
  618 + return;
  619 +
  620 + for (i = 0; i < NR_CPUS; i++) {
  621 + if (!chan->buf[i] || chan->buf[i] == prev)
  622 + break;
  623 + relay_close_buf(chan->buf[i]);
  624 + prev = chan->buf[i];
  625 + }
  626 +
  627 + if (chan->last_toobig)
  628 + printk(KERN_WARNING "relay: one or more items not logged "
  629 + "[item size (%Zd) > sub-buffer size (%Zd)]\n",
  630 + chan->last_toobig, chan->subbuf_size);
  631 +
  632 + kref_put(&chan->kref, relay_destroy_channel);
  633 +}
  634 +EXPORT_SYMBOL_GPL(relay_close);
  635 +
  636 +/**
  637 + * relay_flush - close the channel
  638 + * @chan: the channel
  639 + *
  640 + * Flushes all channel buffers i.e. forces buffer switch.
  641 + */
  642 +void relay_flush(struct rchan *chan)
  643 +{
  644 + unsigned int i;
  645 + struct rchan_buf *prev = NULL;
  646 +
  647 + if (!chan)
  648 + return;
  649 +
  650 + for (i = 0; i < NR_CPUS; i++) {
  651 + if (!chan->buf[i] || chan->buf[i] == prev)
  652 + break;
  653 + relay_switch_subbuf(chan->buf[i], 0);
  654 + prev = chan->buf[i];
  655 + }
  656 +}
  657 +EXPORT_SYMBOL_GPL(relay_flush);
  658 +
  659 +/**
  660 + * relay_file_open - open file op for relay files
  661 + * @inode: the inode
  662 + * @filp: the file
  663 + *
  664 + * Increments the channel buffer refcount.
  665 + */
  666 +static int relay_file_open(struct inode *inode, struct file *filp)
  667 +{
  668 + struct rchan_buf *buf = inode->u.generic_ip;
  669 + kref_get(&buf->kref);
  670 + filp->private_data = buf;
  671 +
  672 + return 0;
  673 +}
  674 +
  675 +/**
  676 + * relay_file_mmap - mmap file op for relay files
  677 + * @filp: the file
  678 + * @vma: the vma describing what to map
  679 + *
  680 + * Calls upon relay_mmap_buf to map the file into user space.
  681 + */
  682 +static int relay_file_mmap(struct file *filp, struct vm_area_struct *vma)
  683 +{
  684 + struct rchan_buf *buf = filp->private_data;
  685 + return relay_mmap_buf(buf, vma);
  686 +}
  687 +
  688 +/**
  689 + * relay_file_poll - poll file op for relay files
  690 + * @filp: the file
  691 + * @wait: poll table
  692 + *
  693 + * Poll implemention.
  694 + */
  695 +static unsigned int relay_file_poll(struct file *filp, poll_table *wait)
  696 +{
  697 + unsigned int mask = 0;
  698 + struct rchan_buf *buf = filp->private_data;
  699 +
  700 + if (buf->finalized)
  701 + return POLLERR;
  702 +
  703 + if (filp->f_mode & FMODE_READ) {
  704 + poll_wait(filp, &buf->read_wait, wait);
  705 + if (!relay_buf_empty(buf))
  706 + mask |= POLLIN | POLLRDNORM;
  707 + }
  708 +
  709 + return mask;
  710 +}
  711 +
  712 +/**
  713 + * relay_file_release - release file op for relay files
  714 + * @inode: the inode
  715 + * @filp: the file
  716 + *
  717 + * Decrements the channel refcount, as the filesystem is
  718 + * no longer using it.
  719 + */
  720 +static int relay_file_release(struct inode *inode, struct file *filp)
  721 +{
  722 + struct rchan_buf *buf = filp->private_data;
  723 + kref_put(&buf->kref, relay_remove_buf);
  724 +
  725 + return 0;
  726 +}
  727 +
  728 +/**
  729 + * relay_file_read_consume - update the consumed count for the buffer
  730 + */
  731 +static void relay_file_read_consume(struct rchan_buf *buf,
  732 + size_t read_pos,
  733 + size_t bytes_consumed)
  734 +{
  735 + size_t subbuf_size = buf->chan->subbuf_size;
  736 + size_t n_subbufs = buf->chan->n_subbufs;
  737 + size_t read_subbuf;
  738 +
  739 + if (buf->bytes_consumed + bytes_consumed > subbuf_size) {
  740 + relay_subbufs_consumed(buf->chan, buf->cpu, 1);
  741 + buf->bytes_consumed = 0;
  742 + }
  743 +
  744 + buf->bytes_consumed += bytes_consumed;
  745 + read_subbuf = read_pos / buf->chan->subbuf_size;
  746 + if (buf->bytes_consumed + buf->padding[read_subbuf] == subbuf_size) {
  747 + if ((read_subbuf == buf->subbufs_produced % n_subbufs) &&
  748 + (buf->offset == subbuf_size))
  749 + return;
  750 + relay_subbufs_consumed(buf->chan, buf->cpu, 1);
  751 + buf->bytes_consumed = 0;
  752 + }
  753 +}
  754 +
  755 +/**
  756 + * relay_file_read_avail - boolean, are there unconsumed bytes available?
  757 + */
  758 +static int relay_file_read_avail(struct rchan_buf *buf, size_t read_pos)
  759 +{
  760 + size_t bytes_produced, bytes_consumed, write_offset;
  761 + size_t subbuf_size = buf->chan->subbuf_size;
  762 + size_t n_subbufs = buf->chan->n_subbufs;
  763 + size_t produced = buf->subbufs_produced % n_subbufs;
  764 + size_t consumed = buf->subbufs_consumed % n_subbufs;
  765 +
  766 + write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset;
  767 +
  768 + if (consumed > produced) {
  769 + if ((produced > n_subbufs) &&
  770 + (produced + n_subbufs - consumed <= n_subbufs))
  771 + produced += n_subbufs;
  772 + } else if (consumed == produced) {
  773 + if (buf->offset > subbuf_size) {
  774 + produced += n_subbufs;
  775 + if (buf->subbufs_produced == buf->subbufs_consumed)
  776 + consumed += n_subbufs;
  777 + }
  778 + }
  779 +
  780 + if (buf->offset > subbuf_size)
  781 + bytes_produced = (produced - 1) * subbuf_size + write_offset;
  782 + else
  783 + bytes_produced = produced * subbuf_size + write_offset;
  784 + bytes_consumed = consumed * subbuf_size + buf->bytes_consumed;
  785 +
  786 + if (bytes_produced == bytes_consumed)
  787 + return 0;
  788 +
  789 + relay_file_read_consume(buf, read_pos, 0);
  790 +
  791 + return 1;
  792 +}
  793 +
  794 +/**
  795 + * relay_file_read_subbuf_avail - return bytes available in sub-buffer
  796 + */
  797 +static size_t relay_file_read_subbuf_avail(size_t read_pos,
  798 + struct rchan_buf *buf)
  799 +{
  800 + size_t padding, avail = 0;
  801 + size_t read_subbuf, read_offset, write_subbuf, write_offset;
  802 + size_t subbuf_size = buf->chan->subbuf_size;
  803 +
  804 + write_subbuf = (buf->data - buf->start) / subbuf_size;
  805 + write_offset = buf->offset > subbuf_size ? subbuf_size : buf->offset;
  806 + read_subbuf = read_pos / subbuf_size;
  807 + read_offset = read_pos % subbuf_size;
  808 + padding = buf->padding[read_subbuf];
  809 +
  810 + if (read_subbuf == write_subbuf) {
  811 + if (read_offset + padding < write_offset)
  812 + avail = write_offset - (read_offset + padding);
  813 + } else
  814 + avail = (subbuf_size - padding) - read_offset;
  815 +
  816 + return avail;
  817 +}
  818 +
  819 +/**
  820 + * relay_file_read_start_pos - find the first available byte to read
  821 + *
  822 + * If the read_pos is in the middle of padding, return the
  823 + * position of the first actually available byte, otherwise
  824 + * return the original value.
  825 + */
  826 +static size_t relay_file_read_start_pos(size_t read_pos,
  827 + struct rchan_buf *buf)
  828 +{
  829 + size_t read_subbuf, padding, padding_start, padding_end;
  830 + size_t subbuf_size = buf->chan->subbuf_size;
  831 + size_t n_subbufs = buf->chan->n_subbufs;
  832 +
  833 + read_subbuf = read_pos / subbuf_size;
  834 + padding = buf->padding[read_subbuf];
  835 + padding_start = (read_subbuf + 1) * subbuf_size - padding;
  836 + padding_end = (read_subbuf + 1) * subbuf_size;
  837 + if (read_pos >= padding_start && read_pos < padding_end) {
  838 + read_subbuf = (read_subbuf + 1) % n_subbufs;
  839 + read_pos = read_subbuf * subbuf_size;
  840 + }
  841 +
  842 + return read_pos;
  843 +}
  844 +
  845 +/**
  846 + * relay_file_read_end_pos - return the new read position
  847 + */
  848 +static size_t relay_file_read_end_pos(struct rchan_buf *buf,
  849 + size_t read_pos,
  850 + size_t count)
  851 +{
  852 + size_t read_subbuf, padding, end_pos;
  853 + size_t subbuf_size = buf->chan->subbuf_size;
  854 + size_t n_subbufs = buf->chan->n_subbufs;
  855 +
  856 + read_subbuf = read_pos / subbuf_size;
  857 + padding = buf->padding[read_subbuf];
  858 + if (read_pos % subbuf_size + count + padding == subbuf_size)
  859 + end_pos = (read_subbuf + 1) * subbuf_size;
  860 + else
  861 + end_pos = read_pos + count;
  862 + if (end_pos >= subbuf_size * n_subbufs)
  863 + end_pos = 0;
  864 +
  865 + return end_pos;
  866 +}
  867 +
  868 +/**
  869 + * relay_file_read - read file op for relay files
  870 + * @filp: the file
  871 + * @buffer: the userspace buffer
  872 + * @count: number of bytes to read
  873 + * @ppos: position to read from
  874 + *
  875 + * Reads count bytes or the number of bytes available in the
  876 + * current sub-buffer being read, whichever is smaller.
  877 + */
  878 +static ssize_t relay_file_read(struct file *filp,
  879 + char __user *buffer,
  880 + size_t count,
  881 + loff_t *ppos)
  882 +{
  883 + struct rchan_buf *buf = filp->private_data;
  884 + struct inode *inode = filp->f_dentry->d_inode;
  885 + size_t read_start, avail;
  886 + ssize_t ret = 0;
  887 + void *from;
  888 +
  889 + mutex_lock(&inode->i_mutex);
  890 + if(!relay_file_read_avail(buf, *ppos))
  891 + goto out;
  892 +
  893 + read_start = relay_file_read_start_pos(*ppos, buf);
  894 + avail = relay_file_read_subbuf_avail(read_start, buf);
  895 + if (!avail)
  896 + goto out;
  897 +
  898 + from = buf->start + read_start;
  899 + ret = count = min(count, avail);
  900 + if (copy_to_user(buffer, from, count)) {
  901 + ret = -EFAULT;
  902 + goto out;
  903 + }
  904 + relay_file_read_consume(buf, read_start, count);
  905 + *ppos = relay_file_read_end_pos(buf, read_start, count);
  906 +out:
  907 + mutex_unlock(&inode->i_mutex);
  908 + return ret;
  909 +}
  910 +
  911 +struct file_operations relay_file_operations = {
  912 + .open = relay_file_open,
  913 + .poll = relay_file_poll,
  914 + .mmap = relay_file_mmap,
  915 + .read = relay_file_read,
  916 + .llseek = no_llseek,
  917 + .release = relay_file_release,
  918 +};
  919 +EXPORT_SYMBOL_GPL(relay_file_operations);