aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/Makefile1
-rw-r--r--fs/anon_inodes.c200
-rw-r--r--include/linux/anon_inodes.h16
-rw-r--r--include/linux/magic.h1
-rw-r--r--init/Kconfig10
5 files changed, 228 insertions, 0 deletions
diff --git a/fs/Makefile b/fs/Makefile
index 9edf4112bee0..b5cd46a88cb0 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -22,6 +22,7 @@ endif
22obj-$(CONFIG_INOTIFY) += inotify.o 22obj-$(CONFIG_INOTIFY) += inotify.o
23obj-$(CONFIG_INOTIFY_USER) += inotify_user.o 23obj-$(CONFIG_INOTIFY_USER) += inotify_user.o
24obj-$(CONFIG_EPOLL) += eventpoll.o 24obj-$(CONFIG_EPOLL) += eventpoll.o
25obj-$(CONFIG_ANON_INODES) += anon_inodes.o
25obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o 26obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
26 27
27nfsd-$(CONFIG_NFSD) := nfsctl.o 28nfsd-$(CONFIG_NFSD) := nfsctl.o
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
new file mode 100644
index 000000000000..40fe3a3222e4
--- /dev/null
+++ b/fs/anon_inodes.c
@@ -0,0 +1,200 @@
1/*
2 * fs/anon_inodes.c
3 *
4 * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
5 *
6 * Thanks to Arnd Bergmann for code review and suggestions.
7 * More changes for Thomas Gleixner suggestions.
8 *
9 */
10
11#include <linux/file.h>
12#include <linux/poll.h>
13#include <linux/slab.h>
14#include <linux/init.h>
15#include <linux/fs.h>
16#include <linux/mount.h>
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/magic.h>
20#include <linux/anon_inodes.h>
21
22#include <asm/uaccess.h>
23
24static struct vfsmount *anon_inode_mnt __read_mostly;
25static struct inode *anon_inode_inode;
26static const struct file_operations anon_inode_fops;
27
28static int anon_inodefs_get_sb(struct file_system_type *fs_type, int flags,
29 const char *dev_name, void *data,
30 struct vfsmount *mnt)
31{
32 return get_sb_pseudo(fs_type, "anon_inode:", NULL, ANON_INODE_FS_MAGIC,
33 mnt);
34}
35
36static int anon_inodefs_delete_dentry(struct dentry *dentry)
37{
38 /*
39 * We faked vfs to believe the dentry was hashed when we created it.
40 * Now we restore the flag so that dput() will work correctly.
41 */
42 dentry->d_flags |= DCACHE_UNHASHED;
43 return 1;
44}
45
46static struct file_system_type anon_inode_fs_type = {
47 .name = "anon_inodefs",
48 .get_sb = anon_inodefs_get_sb,
49 .kill_sb = kill_anon_super,
50};
51static struct dentry_operations anon_inodefs_dentry_operations = {
52 .d_delete = anon_inodefs_delete_dentry,
53};
54
55/**
56 * anon_inode_getfd - creates a new file instance by hooking it up to and
57 * anonymous inode, and a dentry that describe the "class"
58 * of the file
59 *
60 * @pfd: [out] pointer to the file descriptor
61 * @dpinode: [out] pointer to the inode
62 * @pfile: [out] pointer to the file struct
63 * @name: [in] name of the "class" of the new file
64 * @fops [in] file operations for the new file
65 * @priv [in] private data for the new file (will be file's private_data)
66 *
67 * Creates a new file by hooking it on a single inode. This is useful for files
68 * that do not need to have a full-fledged inode in order to operate correctly.
69 * All the files created with anon_inode_getfd() will share a single inode, by
70 * hence saving memory and avoiding code duplication for the file/inode/dentry
71 * setup.
72 */
73int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
74 const char *name, const struct file_operations *fops,
75 void *priv)
76{
77 struct qstr this;
78 struct dentry *dentry;
79 struct inode *inode;
80 struct file *file;
81 int error, fd;
82
83 if (IS_ERR(anon_inode_inode))
84 return -ENODEV;
85 file = get_empty_filp();
86 if (!file)
87 return -ENFILE;
88
89 inode = igrab(anon_inode_inode);
90 if (IS_ERR(inode)) {
91 error = PTR_ERR(inode);
92 goto err_put_filp;
93 }
94
95 error = get_unused_fd();
96 if (error < 0)
97 goto err_iput;
98 fd = error;
99
100 /*
101 * Link the inode to a directory entry by creating a unique name
102 * using the inode sequence number.
103 */
104 error = -ENOMEM;
105 this.name = name;
106 this.len = strlen(name);
107 this.hash = 0;
108 dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
109 if (!dentry)
110 goto err_put_unused_fd;
111 dentry->d_op = &anon_inodefs_dentry_operations;
112 /* Do not publish this dentry inside the global dentry hash table */
113 dentry->d_flags &= ~DCACHE_UNHASHED;
114 d_instantiate(dentry, inode);
115
116 file->f_path.mnt = mntget(anon_inode_mnt);
117 file->f_path.dentry = dentry;
118 file->f_mapping = inode->i_mapping;
119
120 file->f_pos = 0;
121 file->f_flags = O_RDWR;
122 file->f_op = fops;
123 file->f_mode = FMODE_READ | FMODE_WRITE;
124 file->f_version = 0;
125 file->private_data = priv;
126
127 fd_install(fd, file);
128
129 *pfd = fd;
130 *pinode = inode;
131 *pfile = file;
132 return 0;
133
134err_put_unused_fd:
135 put_unused_fd(fd);
136err_iput:
137 iput(inode);
138err_put_filp:
139 put_filp(file);
140 return error;
141}
142
143/*
144 * A single inode exist for all anon_inode files. Contrary to pipes,
145 * anon_inode inodes has no per-instance data associated, so we can avoid
146 * the allocation of multiple of them.
147 */
148static struct inode *anon_inode_mkinode(void)
149{
150 struct inode *inode = new_inode(anon_inode_mnt->mnt_sb);
151
152 if (!inode)
153 return ERR_PTR(-ENOMEM);
154
155 inode->i_fop = &anon_inode_fops;
156
157 /*
158 * Mark the inode dirty from the very beginning,
159 * that way it will never be moved to the dirty
160 * list because mark_inode_dirty() will think
161 * that it already _is_ on the dirty list.
162 */
163 inode->i_state = I_DIRTY;
164 inode->i_mode = S_IRUSR | S_IWUSR;
165 inode->i_uid = current->fsuid;
166 inode->i_gid = current->fsgid;
167 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
168 return inode;
169}
170
171static int __init anon_inode_init(void)
172{
173 int error;
174
175 error = register_filesystem(&anon_inode_fs_type);
176 if (error)
177 goto err_exit;
178 anon_inode_mnt = kern_mount(&anon_inode_fs_type);
179 if (IS_ERR(anon_inode_mnt)) {
180 error = PTR_ERR(anon_inode_mnt);
181 goto err_unregister_filesystem;
182 }
183 anon_inode_inode = anon_inode_mkinode();
184 if (IS_ERR(anon_inode_inode)) {
185 error = PTR_ERR(anon_inode_inode);
186 goto err_mntput;
187 }
188
189 return 0;
190
191err_mntput:
192 mntput(anon_inode_mnt);
193err_unregister_filesystem:
194 unregister_filesystem(&anon_inode_fs_type);
195err_exit:
196 panic(KERN_ERR "anon_inode_init() failed (%d)\n", error);
197}
198
199fs_initcall(anon_inode_init);
200
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
new file mode 100644
index 000000000000..b2e1ba325b9a
--- /dev/null
+++ b/include/linux/anon_inodes.h
@@ -0,0 +1,16 @@
1/*
2 * include/linux/anon_inodes.h
3 *
4 * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
5 *
6 */
7
8#ifndef _LINUX_ANON_INODES_H
9#define _LINUX_ANON_INODES_H
10
11int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
12 const char *name, const struct file_operations *fops,
13 void *priv);
14
15#endif /* _LINUX_ANON_INODES_H */
16
diff --git a/include/linux/magic.h b/include/linux/magic.h
index a9c6567fe70c..9d713c03e3da 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -14,6 +14,7 @@
14#define ISOFS_SUPER_MAGIC 0x9660 14#define ISOFS_SUPER_MAGIC 0x9660
15#define JFFS2_SUPER_MAGIC 0x72b6 15#define JFFS2_SUPER_MAGIC 0x72b6
16#define KVMFS_SUPER_MAGIC 0x19700426 16#define KVMFS_SUPER_MAGIC 0x19700426
17#define ANON_INODE_FS_MAGIC 0x09041934
17 18
18#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ 19#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */
19#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ 20#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */
diff --git a/init/Kconfig b/init/Kconfig
index 322b1f8c21b3..a80bd8326bc6 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -475,9 +475,19 @@ config FUTEX
475 support for "fast userspace mutexes". The resulting kernel may not 475 support for "fast userspace mutexes". The resulting kernel may not
476 run glibc-based applications correctly. 476 run glibc-based applications correctly.
477 477
478config ANON_INODES
479 bool "Enable anonymous inode source" if EMBEDDED
480 default y
481 help
482 Anonymous inode source for pseudo-files like epoll, signalfd,
483 timerfd and eventfd.
484
485 If unsure, say Y.
486
478config EPOLL 487config EPOLL
479 bool "Enable eventpoll support" if EMBEDDED 488 bool "Enable eventpoll support" if EMBEDDED
480 default y 489 default y
490 depends on ANON_INODES
481 help 491 help
482 Disabling this option will cause the kernel to be built without 492 Disabling this option will cause the kernel to be built without
483 support for epoll family of system calls. 493 support for epoll family of system calls.