2 * VFS-related code for RelayFS, a high-speed data relay filesystem.
4 * Copyright (C) 2003 - Tom Zanussi <zanussi@us.ibm.com>, IBM Corp
5 * Copyright (C) 2003 - Karim Yaghmour <karim@opersys.com>
7 * Based on ramfs, Copyright (C) 2002 - Linus Torvalds
9 * This file is released under the GPL.
12 #include <linux/module.h>
14 #include <linux/mount.h>
15 #include <linux/pagemap.h>
16 #include <linux/highmem.h>
17 #include <linux/init.h>
18 #include <linux/string.h>
19 #include <linux/smp_lock.h>
20 #include <linux/backing-dev.h>
21 #include <linux/namei.h>
22 #include <linux/poll.h>
23 #include <asm/uaccess.h>
24 #include <asm/relay.h>
26 #define RELAYFS_MAGIC 0x26F82121
28 static struct super_operations relayfs_ops;
29 static struct address_space_operations relayfs_aops;
30 static struct inode_operations relayfs_file_inode_operations;
31 static struct file_operations relayfs_file_operations;
32 static struct inode_operations relayfs_dir_inode_operations;
34 static struct vfsmount * relayfs_mount;
35 static int relayfs_mount_count;
37 static struct backing_dev_info relayfs_backing_dev_info = {
38 .ra_pages = 0, /* No readahead */
39 .memory_backed = 1, /* Does not contribute to dirty memory */
43 relayfs_get_inode(struct super_block *sb, int mode, dev_t dev)
47 inode = new_inode(sb);
51 inode->i_uid = current->fsuid;
52 inode->i_gid = current->fsgid;
53 inode->i_blksize = PAGE_CACHE_SIZE;
55 inode->i_mapping->a_ops = &relayfs_aops;
56 inode->i_mapping->backing_dev_info = &relayfs_backing_dev_info;
57 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
58 switch (mode & S_IFMT) {
60 init_special_inode(inode, mode, dev);
63 inode->i_op = &relayfs_file_inode_operations;
64 inode->i_fop = &relayfs_file_operations;
67 inode->i_op = &relayfs_dir_inode_operations;
68 inode->i_fop = &simple_dir_operations;
70 /* directory inodes start off with i_nlink == 2 (for "." entry) */
74 inode->i_op = &page_symlink_inode_operations;
82 * File creation. Allocate an inode, and we're done..
86 relayfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
91 inode = relayfs_get_inode(dir->i_sb, mode, dev);
94 d_instantiate(dentry, inode);
95 dget(dentry); /* Extra count - pin the dentry in core */
102 relayfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
106 retval = relayfs_mknod(dir, dentry, mode | S_IFDIR, 0);
114 relayfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
116 return relayfs_mknod(dir, dentry, mode | S_IFREG, 0);
120 relayfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
125 inode = relayfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
128 int l = strlen(symname)+1;
129 error = page_symlink(inode, symname, l);
131 d_instantiate(dentry, inode);
140 * relayfs_create_entry - create a relayfs directory or file
141 * @name: the name of the file to create
142 * @parent: parent directory
143 * @dentry: result dentry
144 * @entry_type: type of file to create (S_IFREG, S_IFDIR)
146 * @data: data to associate with the file
148 * Creates a file or directory with the specifed permissions.
151 relayfs_create_entry(const char * name, struct dentry * parent, struct dentry **dentry, int entry_type, int mode, void * data)
158 error = simple_pin_fs("relayfs", &relayfs_mount, &relayfs_mount_count);
160 printk(KERN_ERR "Couldn't mount relayfs: errcode %d\n", error);
165 qname.len = strlen(name);
166 qname.hash = full_name_hash(name, qname.len);
169 if (relayfs_mount && relayfs_mount->mnt_sb)
170 parent = relayfs_mount->mnt_sb->s_root;
172 if (parent == NULL) {
173 simple_release_fs(&relayfs_mount, &relayfs_mount_count);
177 parent = dget(parent);
178 down(&parent->d_inode->i_sem);
179 d = lookup_hash(&qname, parent);
190 if (entry_type == S_IFREG)
191 error = relayfs_create(parent->d_inode, d, entry_type | mode, NULL);
193 error = relayfs_mkdir(parent->d_inode, d, entry_type | mode);
197 if ((entry_type == S_IFREG) && data) {
198 d->d_inode->u.generic_ip = data;
199 goto exit; /* don't release mount for regular files */
203 simple_release_fs(&relayfs_mount, &relayfs_mount_count);
206 up(&parent->d_inode->i_sem);
213 * relayfs_create_file - create a file in the relay filesystem
214 * @name: the name of the file to create
215 * @parent: parent directory
216 * @dentry: result dentry
217 * @data: data to associate with the file
218 * @mode: mode, if not specied the default perms are used
220 * The file will be created user rw on behalf of current user.
223 relayfs_create_file(const char * name, struct dentry * parent, struct dentry **dentry, void * data, int mode)
226 mode = S_IRUSR | S_IWUSR;
228 return relayfs_create_entry(name, parent, dentry, S_IFREG,
233 * relayfs_create_dir - create a directory in the relay filesystem
234 * @name: the name of the directory to create
235 * @parent: parent directory
236 * @dentry: result dentry
238 * The directory will be created world rwx on behalf of current user.
241 relayfs_create_dir(const char * name, struct dentry * parent, struct dentry **dentry)
243 return relayfs_create_entry(name, parent, dentry, S_IFDIR,
244 S_IRWXU | S_IRUGO | S_IXUGO, NULL);
248 * relayfs_remove_file - remove a file in the relay filesystem
249 * @dentry: file dentry
251 * Remove a file previously created by relayfs_create_file.
254 relayfs_remove_file(struct dentry *dentry)
256 struct dentry *parent;
259 parent = dentry->d_parent;
263 is_reg = S_ISREG(dentry->d_inode->i_mode);
265 parent = dget(parent);
266 down(&parent->d_inode->i_sem);
267 if (dentry->d_inode) {
268 simple_unlink(parent->d_inode, dentry);
272 up(&parent->d_inode->i_sem);
276 simple_release_fs(&relayfs_mount, &relayfs_mount_count);
282 * relayfs_open - open file op for relayfs files
286 * Associates the channel with the file, and increments the
287 * channel refcount. Reads will be 'auto-consuming'.
290 relayfs_open(struct inode *inode, struct file *filp)
293 struct rchan_reader *reader;
296 if (inode->u.generic_ip) {
297 rchan = (struct rchan *)inode->u.generic_ip;
300 reader = __add_rchan_reader(rchan, filp, 1, 0);
303 filp->private_data = reader;
304 retval = rchan->callbacks->fileop_notify(rchan->id, filp,
307 /* Inc relay channel refcount for file */
308 rchan_get(rchan->id);
310 __remove_rchan_reader(reader);
319 * relayfs_mmap - mmap file op for relayfs files
321 * @vma: the vma describing what to map
323 * Calls upon relay_mmap_buffer to map the file into user space.
326 relayfs_mmap(struct file *filp, struct vm_area_struct *vma)
330 rchan = ((struct rchan_reader *)filp->private_data)->rchan;
332 return __relay_mmap_buffer(rchan, vma);
336 * relayfs_file_read - read file op for relayfs files
338 * @buf: user buf to read into
339 * @count: bytes requested
340 * @offset: offset into file
342 * Reads count bytes from the channel, or as much as is available within
343 * the sub-buffer currently being read. Reads are 'auto-consuming'.
344 * See relay_read() for details.
346 * Returns bytes read on success, 0 or -EAGAIN if nothing available,
347 * negative otherwise.
350 relayfs_file_read(struct file *filp, char * buf, size_t count, loff_t *offset)
353 struct rchan_reader *reader;
354 u32 dummy; /* all VFS readers are auto-consuming */
356 if (offset != &filp->f_pos) /* pread, seeking not supported */
362 reader = (struct rchan_reader *)filp->private_data;
363 read_count = relay_read(reader, buf, count,
364 filp->f_flags & (O_NDELAY | O_NONBLOCK) ? 0 : 1, &dummy);
370 * relayfs_file_write - write file op for relayfs files
372 * @buf: user buf to write from
373 * @count: bytes to write
374 * @offset: offset into file
376 * Reserves a slot in the relay buffer and writes count bytes
377 * into it. The current limit for a single write is 2 pages
378 * worth. The user_deliver() channel callback will be invoked on
380 * Returns bytes written on success, 0 or -EAGAIN if nothing available,
381 * negative otherwise.
384 relayfs_file_write(struct file *filp, const char *buf, size_t count, loff_t *offset)
391 struct rchan_reader *reader;
393 reader = (struct rchan_reader *)filp->private_data;
397 rchan = reader->rchan;
404 /* Change this if need to write more than 2 pages at once */
405 if (count > 2 * PAGE_SIZE)
408 write_buf = (char *)__get_free_pages(GFP_KERNEL, 1);
409 if (write_buf == NULL)
412 if (copy_from_user(write_buf, buf, count))
415 if (filp->f_flags & (O_NDELAY | O_NONBLOCK)) {
416 write_count = relay_write(rchan->id, write_buf, count, -1, &wrote_pos);
417 if (write_count == 0)
420 err = wait_event_interruptible(rchan->write_wait,
421 (write_count = relay_write(rchan->id, write_buf, count, -1, &wrote_pos)));
426 free_pages((unsigned long)write_buf, 1);
428 rchan->callbacks->user_deliver(rchan->id, wrote_pos, write_count);
434 * relayfs_ioctl - ioctl file op for relayfs files
440 * Passes the specified cmd/arg to the kernel client. arg may be a
441 * pointer to user-space data, in which case the kernel client is
442 * responsible for copying the data to/from user space appropriately.
443 * The kernel client is also responsible for returning a meaningful
444 * return value for ioctl calls.
446 * Returns result of relay channel callback, -EPERM if unsuccessful.
449 relayfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
452 struct rchan_reader *reader;
454 reader = (struct rchan_reader *)filp->private_data;
458 rchan = reader->rchan;
462 return rchan->callbacks->ioctl(rchan->id, cmd, arg);
466 * relayfs_poll - poll file op for relayfs files
473 relayfs_poll(struct file *filp, poll_table *wait)
475 struct rchan_reader *reader;
476 unsigned int mask = 0;
478 reader = (struct rchan_reader *)filp->private_data;
480 if (reader->rchan->finalized)
483 if (filp->f_mode & FMODE_READ) {
484 poll_wait(filp, &reader->rchan->read_wait, wait);
485 if (!rchan_empty(reader))
486 mask |= POLLIN | POLLRDNORM;
489 if (filp->f_mode & FMODE_WRITE) {
490 poll_wait(filp, &reader->rchan->write_wait, wait);
491 if (!rchan_full(reader))
492 mask |= POLLOUT | POLLWRNORM;
499 * relayfs_release - release file op for relayfs files
503 * Decrements the channel refcount, as the filesystem is
504 * no longer using it.
507 relayfs_release(struct inode *inode, struct file *filp)
509 struct rchan_reader *reader;
512 reader = (struct rchan_reader *)filp->private_data;
513 if (reader == NULL || reader->rchan == NULL)
515 rchan = reader->rchan;
517 rchan->callbacks->fileop_notify(reader->rchan->id, filp,
519 __remove_rchan_reader(reader);
520 /* The channel is no longer in use as far as this file is concerned */
526 static struct address_space_operations relayfs_aops = {
527 .readpage = simple_readpage,
528 .prepare_write = simple_prepare_write,
529 .commit_write = simple_commit_write
532 static struct file_operations relayfs_file_operations = {
533 .open = relayfs_open,
534 .read = relayfs_file_read,
535 .write = relayfs_file_write,
536 .ioctl = relayfs_ioctl,
537 .poll = relayfs_poll,
538 .mmap = relayfs_mmap,
539 .fsync = simple_sync_file,
540 .release = relayfs_release,
543 static struct inode_operations relayfs_file_inode_operations = {
544 .getattr = simple_getattr,
547 static struct inode_operations relayfs_dir_inode_operations = {
548 .create = relayfs_create,
549 .lookup = simple_lookup,
551 .unlink = simple_unlink,
552 .symlink = relayfs_symlink,
553 .mkdir = relayfs_mkdir,
554 .rmdir = simple_rmdir,
555 .mknod = relayfs_mknod,
556 .rename = simple_rename,
559 static struct super_operations relayfs_ops = {
560 .statfs = simple_statfs,
561 .drop_inode = generic_delete_inode,
565 relayfs_fill_super(struct super_block * sb, void * data, int silent)
567 struct inode * inode;
568 struct dentry * root;
570 sb->s_blocksize = PAGE_CACHE_SIZE;
571 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
572 sb->s_magic = RELAYFS_MAGIC;
573 sb->s_op = &relayfs_ops;
574 inode = relayfs_get_inode(sb, S_IFDIR | 0755, 0);
579 root = d_alloc_root(inode);
589 static struct super_block *
590 relayfs_get_sb(struct file_system_type *fs_type,
591 int flags, const char *dev_name, void *data)
593 return get_sb_single(fs_type, flags, data, relayfs_fill_super);
596 static struct file_system_type relayfs_fs_type = {
597 .owner = THIS_MODULE,
599 .get_sb = relayfs_get_sb,
600 .kill_sb = kill_litter_super,
604 init_relayfs_fs(void)
606 int err = register_filesystem(&relayfs_fs_type);
607 #ifdef CONFIG_KLOG_CHANNEL
609 create_klog_channel();
615 exit_relayfs_fs(void)
617 #ifdef CONFIG_KLOG_CHANNEL
618 remove_klog_channel();
620 unregister_filesystem(&relayfs_fs_type);
623 module_init(init_relayfs_fs)
624 module_exit(exit_relayfs_fs)
626 MODULE_AUTHOR("Tom Zanussi <zanussi@us.ibm.com> and Karim Yaghmour <karim@opersys.com>");
627 MODULE_DESCRIPTION("Relay Filesystem");
628 MODULE_LICENSE("GPL");