diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/anon_inodes.c | 109 |
1 files changed, 56 insertions, 53 deletions
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index f11e43ed907d..28d39fb84ae3 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c | |||
@@ -39,19 +39,6 @@ static const struct dentry_operations anon_inodefs_dentry_operations = { | |||
39 | .d_dname = anon_inodefs_dname, | 39 | .d_dname = anon_inodefs_dname, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type, | ||
43 | int flags, const char *dev_name, void *data) | ||
44 | { | ||
45 | return mount_pseudo(fs_type, "anon_inode:", NULL, | ||
46 | &anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC); | ||
47 | } | ||
48 | |||
49 | static struct file_system_type anon_inode_fs_type = { | ||
50 | .name = "anon_inodefs", | ||
51 | .mount = anon_inodefs_mount, | ||
52 | .kill_sb = kill_anon_super, | ||
53 | }; | ||
54 | |||
55 | /* | 42 | /* |
56 | * nop .set_page_dirty method so that people can use .page_mkwrite on | 43 | * nop .set_page_dirty method so that people can use .page_mkwrite on |
57 | * anon inodes. | 44 | * anon inodes. |
@@ -65,6 +52,62 @@ static const struct address_space_operations anon_aops = { | |||
65 | .set_page_dirty = anon_set_page_dirty, | 52 | .set_page_dirty = anon_set_page_dirty, |
66 | }; | 53 | }; |
67 | 54 | ||
55 | /* | ||
56 | * A single inode exists for all anon_inode files. Contrary to pipes, | ||
57 | * anon_inode inodes have no associated per-instance data, so we need | ||
58 | * only allocate one of them. | ||
59 | */ | ||
60 | static struct inode *anon_inode_mkinode(struct super_block *s) | ||
61 | { | ||
62 | struct inode *inode = new_inode_pseudo(s); | ||
63 | |||
64 | if (!inode) | ||
65 | return ERR_PTR(-ENOMEM); | ||
66 | |||
67 | inode->i_ino = get_next_ino(); | ||
68 | inode->i_fop = &anon_inode_fops; | ||
69 | |||
70 | inode->i_mapping->a_ops = &anon_aops; | ||
71 | |||
72 | /* | ||
73 | * Mark the inode dirty from the very beginning, | ||
74 | * that way it will never be moved to the dirty | ||
75 | * list because mark_inode_dirty() will think | ||
76 | * that it already _is_ on the dirty list. | ||
77 | */ | ||
78 | inode->i_state = I_DIRTY; | ||
79 | inode->i_mode = S_IRUSR | S_IWUSR; | ||
80 | inode->i_uid = current_fsuid(); | ||
81 | inode->i_gid = current_fsgid(); | ||
82 | inode->i_flags |= S_PRIVATE; | ||
83 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
84 | return inode; | ||
85 | } | ||
86 | |||
87 | static struct dentry *anon_inodefs_mount(struct file_system_type *fs_type, | ||
88 | int flags, const char *dev_name, void *data) | ||
89 | { | ||
90 | struct dentry *root; | ||
91 | root = mount_pseudo(fs_type, "anon_inode:", NULL, | ||
92 | &anon_inodefs_dentry_operations, ANON_INODE_FS_MAGIC); | ||
93 | if (!IS_ERR(root)) { | ||
94 | struct super_block *s = root->d_sb; | ||
95 | anon_inode_inode = anon_inode_mkinode(s); | ||
96 | if (IS_ERR(anon_inode_inode)) { | ||
97 | dput(root); | ||
98 | deactivate_locked_super(s); | ||
99 | root = ERR_CAST(anon_inode_inode); | ||
100 | } | ||
101 | } | ||
102 | return root; | ||
103 | } | ||
104 | |||
105 | static struct file_system_type anon_inode_fs_type = { | ||
106 | .name = "anon_inodefs", | ||
107 | .mount = anon_inodefs_mount, | ||
108 | .kill_sb = kill_anon_super, | ||
109 | }; | ||
110 | |||
68 | /** | 111 | /** |
69 | * anon_inode_getfile - creates a new file instance by hooking it up to an | 112 | * anon_inode_getfile - creates a new file instance by hooking it up to an |
70 | * anonymous inode, and a dentry that describe the "class" | 113 | * anonymous inode, and a dentry that describe the "class" |
@@ -180,38 +223,6 @@ err_put_unused_fd: | |||
180 | } | 223 | } |
181 | EXPORT_SYMBOL_GPL(anon_inode_getfd); | 224 | EXPORT_SYMBOL_GPL(anon_inode_getfd); |
182 | 225 | ||
183 | /* | ||
184 | * A single inode exists for all anon_inode files. Contrary to pipes, | ||
185 | * anon_inode inodes have no associated per-instance data, so we need | ||
186 | * only allocate one of them. | ||
187 | */ | ||
188 | static struct inode *anon_inode_mkinode(void) | ||
189 | { | ||
190 | struct inode *inode = new_inode_pseudo(anon_inode_mnt->mnt_sb); | ||
191 | |||
192 | if (!inode) | ||
193 | return ERR_PTR(-ENOMEM); | ||
194 | |||
195 | inode->i_ino = get_next_ino(); | ||
196 | inode->i_fop = &anon_inode_fops; | ||
197 | |||
198 | inode->i_mapping->a_ops = &anon_aops; | ||
199 | |||
200 | /* | ||
201 | * Mark the inode dirty from the very beginning, | ||
202 | * that way it will never be moved to the dirty | ||
203 | * list because mark_inode_dirty() will think | ||
204 | * that it already _is_ on the dirty list. | ||
205 | */ | ||
206 | inode->i_state = I_DIRTY; | ||
207 | inode->i_mode = S_IRUSR | S_IWUSR; | ||
208 | inode->i_uid = current_fsuid(); | ||
209 | inode->i_gid = current_fsgid(); | ||
210 | inode->i_flags |= S_PRIVATE; | ||
211 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
212 | return inode; | ||
213 | } | ||
214 | |||
215 | static int __init anon_inode_init(void) | 226 | static int __init anon_inode_init(void) |
216 | { | 227 | { |
217 | int error; | 228 | int error; |
@@ -224,16 +235,8 @@ static int __init anon_inode_init(void) | |||
224 | error = PTR_ERR(anon_inode_mnt); | 235 | error = PTR_ERR(anon_inode_mnt); |
225 | goto err_unregister_filesystem; | 236 | goto err_unregister_filesystem; |
226 | } | 237 | } |
227 | anon_inode_inode = anon_inode_mkinode(); | ||
228 | if (IS_ERR(anon_inode_inode)) { | ||
229 | error = PTR_ERR(anon_inode_inode); | ||
230 | goto err_mntput; | ||
231 | } | ||
232 | |||
233 | return 0; | 238 | return 0; |
234 | 239 | ||
235 | err_mntput: | ||
236 | kern_unmount(anon_inode_mnt); | ||
237 | err_unregister_filesystem: | 240 | err_unregister_filesystem: |
238 | unregister_filesystem(&anon_inode_fs_type); | 241 | unregister_filesystem(&anon_inode_fs_type); |
239 | err_exit: | 242 | err_exit: |