aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/Kconfig12
-rw-r--r--fs/Makefile1
-rw-r--r--fs/relayfs/Makefile4
-rw-r--r--fs/relayfs/buffers.c190
-rw-r--r--fs/relayfs/buffers.h12
-rw-r--r--fs/relayfs/inode.c581
-rw-r--r--fs/relayfs/relay.c482
-rw-r--r--fs/relayfs/relay.h8
-rw-r--r--include/linux/relay.h281
-rw-r--r--init/Kconfig11
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/relay.c919
12 files changed, 1212 insertions, 1290 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index e9749b0eecd8..c8d0a209120c 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -859,18 +859,6 @@ config RAMFS
859 To compile this as a module, choose M here: the module will be called 859 To compile this as a module, choose M here: the module will be called
860 ramfs. 860 ramfs.
861 861
862config 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
874config CONFIGFS_FS 862config CONFIGFS_FS
875 tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)" 863 tristate "Userspace-driven configuration filesystem (EXPERIMENTAL)"
876 depends on EXPERIMENTAL 864 depends on EXPERIMENTAL
diff --git a/fs/Makefile b/fs/Makefile
index 1db711319c80..080b3867be4d 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -91,7 +91,6 @@ obj-$(CONFIG_AUTOFS4_FS) += autofs4/
91obj-$(CONFIG_ADFS_FS) += adfs/ 91obj-$(CONFIG_ADFS_FS) += adfs/
92obj-$(CONFIG_FUSE_FS) += fuse/ 92obj-$(CONFIG_FUSE_FS) += fuse/
93obj-$(CONFIG_UDF_FS) += udf/ 93obj-$(CONFIG_UDF_FS) += udf/
94obj-$(CONFIG_RELAYFS_FS) += relayfs/
95obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/ 94obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
96obj-$(CONFIG_JFS_FS) += jfs/ 95obj-$(CONFIG_JFS_FS) += jfs/
97obj-$(CONFIG_XFS_FS) += xfs/ 96obj-$(CONFIG_XFS_FS) += xfs/
diff --git a/fs/relayfs/Makefile b/fs/relayfs/Makefile
deleted file mode 100644
index e76e182cdb38..000000000000
--- a/fs/relayfs/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
1obj-$(CONFIG_RELAYFS_FS) += relayfs.o
2
3relayfs-y := relay.o inode.o buffers.o
4
diff --git a/fs/relayfs/buffers.c b/fs/relayfs/buffers.c
deleted file mode 100644
index 10187812771e..000000000000
--- a/fs/relayfs/buffers.c
+++ /dev/null
@@ -1,190 +0,0 @@
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 */
20static 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 */
29static 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 */
56static 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 */
70int 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 */
95static 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
120depopulate:
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 */
134struct 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
152free_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 */
162void 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 */
185void 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}
diff --git a/fs/relayfs/buffers.h b/fs/relayfs/buffers.h
deleted file mode 100644
index 37a12493f641..000000000000
--- a/fs/relayfs/buffers.h
+++ /dev/null
@@ -1,12 +0,0 @@
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
7extern int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma);
8extern struct rchan_buf *relay_create_buf(struct rchan *chan);
9extern void relay_destroy_buf(struct rchan_buf *buf);
10extern void relay_remove_buf(struct kref *kref);
11
12#endif/* _BUFFERS_H */
diff --git a/fs/relayfs/inode.c b/fs/relayfs/inode.c
deleted file mode 100644
index 383523011aad..000000000000
--- a/fs/relayfs/inode.c
+++ /dev/null
@@ -1,581 +0,0 @@
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
27static struct vfsmount * relayfs_mount;
28static int relayfs_mount_count;
29
30static 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
35static 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 */
85static 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
138release_mount:
139 simple_release_fs(&relayfs_mount, &relayfs_mount_count);
140
141exit:
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 */
159struct 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 */
183struct 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 */
195int 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 */
233int 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 */
244int 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 */
256static 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 */
272static 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 */
285static 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 */
310static 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 */
321static 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 */
348static 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 */
387static 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 */
416static 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 */
438static 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 */
468static 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);
496out:
497 mutex_unlock(&inode->i_mutex);
498 return ret;
499}
500
501struct 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
510static struct super_operations relayfs_ops = {
511 .statfs = simple_statfs,
512 .drop_inode = generic_delete_inode,
513};
514
515static 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
540static 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
547static 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
554static int __init init_relayfs_fs(void)
555{
556 return register_filesystem(&relayfs_fs_type);
557}
558
559static void __exit exit_relayfs_fs(void)
560{
561
562
563
564
565
566 unregister_filesystem(&relayfs_fs_type);
567}
568
569module_init(init_relayfs_fs)
570module_exit(exit_relayfs_fs)
571
572EXPORT_SYMBOL_GPL(relay_file_operations);
573EXPORT_SYMBOL_GPL(relayfs_create_dir);
574EXPORT_SYMBOL_GPL(relayfs_remove_dir);
575EXPORT_SYMBOL_GPL(relayfs_create_file);
576EXPORT_SYMBOL_GPL(relayfs_remove_file);
577
578MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>");
579MODULE_DESCRIPTION("Relay Filesystem");
580MODULE_LICENSE("GPL");
581
diff --git a/fs/relayfs/relay.c b/fs/relayfs/relay.c
deleted file mode 100644
index abf3ceaace49..000000000000
--- a/fs/relayfs/relay.c
+++ /dev/null
@@ -1,482 +0,0 @@
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 */
27int 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 */
38int 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 */
56static 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 */
70static 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 */
78static 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 */
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
104/* relay channel default callbacks */
105static 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 */
121static 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 */
134static 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 */
171void 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 */
192static 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 */
229static 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
238static 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 */
274struct 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
318free_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
328free_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 */
343size_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
378toobig:
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 */
396void 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 */
419void 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 */
431void 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 */
460void 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
476EXPORT_SYMBOL_GPL(relay_open);
477EXPORT_SYMBOL_GPL(relay_close);
478EXPORT_SYMBOL_GPL(relay_flush);
479EXPORT_SYMBOL_GPL(relay_reset);
480EXPORT_SYMBOL_GPL(relay_subbufs_consumed);
481EXPORT_SYMBOL_GPL(relay_switch_subbuf);
482EXPORT_SYMBOL_GPL(relay_buf_full);
diff --git a/fs/relayfs/relay.h b/fs/relayfs/relay.h
deleted file mode 100644
index 0993d3e5753b..000000000000
--- a/fs/relayfs/relay.h
+++ /dev/null
@@ -1,8 +0,0 @@
1#ifndef _RELAY_H
2#define _RELAY_H
3
4extern int relayfs_remove(struct dentry *dentry);
5extern int relay_buf_empty(struct rchan_buf *buf);
6extern void relay_destroy_channel(struct kref *kref);
7
8#endif /* _RELAY_H */
diff --git a/include/linux/relay.h b/include/linux/relay.h
new file mode 100644
index 000000000000..4bcc1531d6a9
--- /dev/null
+++ b/include/linux/relay.h
@@ -0,0 +1,281 @@
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 */
33struct 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 */
57struct 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 */
73struct 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
162struct 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);
167extern void relay_close(struct rchan *chan);
168extern void relay_flush(struct rchan *chan);
169extern void relay_subbufs_consumed(struct rchan *chan,
170 unsigned int cpu,
171 size_t consumed);
172extern void relay_reset(struct rchan *chan);
173extern int relay_buf_full(struct rchan_buf *buf);
174
175extern 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 */
191static 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 */
219static 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 */
244static 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 */
268static 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 */
278extern struct file_operations relay_file_operations;
279
280#endif /* _LINUX_RELAY_H */
281
diff --git a/init/Kconfig b/init/Kconfig
index 38416a199def..1d19fd25204b 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -214,6 +214,17 @@ config CPUSETS
214 214
215 Say N if unsure. 215 Say N if unsure.
216 216
217config 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
217source "usr/Kconfig" 228source "usr/Kconfig"
218 229
219config UID16 230config UID16
diff --git a/kernel/Makefile b/kernel/Makefile
index 4ae0fbde815d..aebd7a78984e 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
34obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ 34obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
35obj-$(CONFIG_SECCOMP) += seccomp.o 35obj-$(CONFIG_SECCOMP) += seccomp.o
36obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o 36obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
37obj-$(CONFIG_RELAY) += relay.o
37 38
38ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) 39ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
39# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is 40# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff --git a/kernel/relay.c b/kernel/relay.c
new file mode 100644
index 000000000000..9358e8eb8476
--- /dev/null
+++ b/kernel/relay.c
@@ -0,0 +1,919 @@
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 */
25static 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 */
34static 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 */
61static 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 */
75int 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 */
100static 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
125depopulate:
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 */
139struct 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
157free_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 */
168void 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 */
178void 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 */
201void 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 */
214int relay_buf_empty(struct rchan_buf *buf)
215{
216 return (buf->subbufs_produced - buf->subbufs_consumed) ? 0 : 1;
217}
218EXPORT_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 */
226int 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}
231EXPORT_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 */
245static 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 */
259static 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 */
267static 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 */
275static 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 */
287static int remove_buf_file_default_callback(struct dentry *dentry)
288{
289 return -EINVAL;
290}
291
292/* relay channel default callbacks */
293static 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 */
309static 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 */
322static 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 */
359void 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}
374EXPORT_SYMBOL_GPL(relay_reset);
375
376/**
377 * relay_open_buf - create a new relay channel buffer
378 *
379 * Internal - used by relay_open().
380 */
381static 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 */
418static 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
426static 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 */
462struct 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
507free_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
517free_chan:
518 kref_put(&chan->kref, relay_destroy_channel);
519 return NULL;
520}
521EXPORT_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 */
533size_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
568toobig:
569 buf->chan->last_toobig = length;
570 return 0;
571}
572EXPORT_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 */
587void 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}
604EXPORT_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 */
612void 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}
634EXPORT_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 */
642void 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}
657EXPORT_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 */
666static 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 */
682static 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 */
695static 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 */
720static 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 */
731static 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 */
758static 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 */
797static 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 */
826static 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 */
848static 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 */
878static 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);
906out:
907 mutex_unlock(&inode->i_mutex);
908 return ret;
909}
910
911struct 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};
919EXPORT_SYMBOL_GPL(relay_file_operations);