aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2006-03-23 13:56:55 -0500
committerJens Axboe <axboe@suse.de>2006-03-23 13:56:55 -0500
commitb86ff981a8252d83d6a7719ae09f3a05307e3592 (patch)
treeba8839f46cb140664e6a1ff6c7361b7424a95a7f /fs
parentb0e6e962992b76580f4900b166a337bad7c1e81b (diff)
[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>
Diffstat (limited to 'fs')
-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
8 files changed, 0 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 */