diff options
Diffstat (limited to 'fs/ramfs')
-rw-r--r-- | fs/ramfs/inode.c | 94 |
1 files changed, 86 insertions, 8 deletions
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index b7e6ac706b87..a404fb88e456 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c | |||
@@ -33,12 +33,15 @@ | |||
33 | #include <linux/backing-dev.h> | 33 | #include <linux/backing-dev.h> |
34 | #include <linux/ramfs.h> | 34 | #include <linux/ramfs.h> |
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/parser.h> | ||
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
37 | #include "internal.h" | 38 | #include "internal.h" |
38 | 39 | ||
39 | /* some random number */ | 40 | /* some random number */ |
40 | #define RAMFS_MAGIC 0x858458f6 | 41 | #define RAMFS_MAGIC 0x858458f6 |
41 | 42 | ||
43 | #define RAMFS_DEFAULT_MODE 0755 | ||
44 | |||
42 | static const struct super_operations ramfs_ops; | 45 | static const struct super_operations ramfs_ops; |
43 | static const struct inode_operations ramfs_dir_inode_operations; | 46 | static const struct inode_operations ramfs_dir_inode_operations; |
44 | 47 | ||
@@ -158,12 +161,75 @@ static const struct inode_operations ramfs_dir_inode_operations = { | |||
158 | static const struct super_operations ramfs_ops = { | 161 | static const struct super_operations ramfs_ops = { |
159 | .statfs = simple_statfs, | 162 | .statfs = simple_statfs, |
160 | .drop_inode = generic_delete_inode, | 163 | .drop_inode = generic_delete_inode, |
164 | .show_options = generic_show_options, | ||
165 | }; | ||
166 | |||
167 | struct ramfs_mount_opts { | ||
168 | umode_t mode; | ||
169 | }; | ||
170 | |||
171 | enum { | ||
172 | Opt_mode, | ||
173 | Opt_err | ||
174 | }; | ||
175 | |||
176 | static const match_table_t tokens = { | ||
177 | {Opt_mode, "mode=%o"}, | ||
178 | {Opt_err, NULL} | ||
179 | }; | ||
180 | |||
181 | struct ramfs_fs_info { | ||
182 | struct ramfs_mount_opts mount_opts; | ||
161 | }; | 183 | }; |
162 | 184 | ||
185 | static int ramfs_parse_options(char *data, struct ramfs_mount_opts *opts) | ||
186 | { | ||
187 | substring_t args[MAX_OPT_ARGS]; | ||
188 | int option; | ||
189 | int token; | ||
190 | char *p; | ||
191 | |||
192 | opts->mode = RAMFS_DEFAULT_MODE; | ||
193 | |||
194 | while ((p = strsep(&data, ",")) != NULL) { | ||
195 | if (!*p) | ||
196 | continue; | ||
197 | |||
198 | token = match_token(p, tokens, args); | ||
199 | switch (token) { | ||
200 | case Opt_mode: | ||
201 | if (match_octal(&args[0], &option)) | ||
202 | return -EINVAL; | ||
203 | opts->mode = option & S_IALLUGO; | ||
204 | break; | ||
205 | default: | ||
206 | printk(KERN_ERR "ramfs: bad mount option: %s\n", p); | ||
207 | return -EINVAL; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
163 | static int ramfs_fill_super(struct super_block * sb, void * data, int silent) | 214 | static int ramfs_fill_super(struct super_block * sb, void * data, int silent) |
164 | { | 215 | { |
165 | struct inode * inode; | 216 | struct ramfs_fs_info *fsi; |
166 | struct dentry * root; | 217 | struct inode *inode = NULL; |
218 | struct dentry *root; | ||
219 | int err; | ||
220 | |||
221 | save_mount_options(sb, data); | ||
222 | |||
223 | fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL); | ||
224 | if (!fsi) { | ||
225 | err = -ENOMEM; | ||
226 | goto fail; | ||
227 | } | ||
228 | sb->s_fs_info = fsi; | ||
229 | |||
230 | err = ramfs_parse_options(data, &fsi->mount_opts); | ||
231 | if (err) | ||
232 | goto fail; | ||
167 | 233 | ||
168 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 234 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
169 | sb->s_blocksize = PAGE_CACHE_SIZE; | 235 | sb->s_blocksize = PAGE_CACHE_SIZE; |
@@ -171,17 +237,23 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent) | |||
171 | sb->s_magic = RAMFS_MAGIC; | 237 | sb->s_magic = RAMFS_MAGIC; |
172 | sb->s_op = &ramfs_ops; | 238 | sb->s_op = &ramfs_ops; |
173 | sb->s_time_gran = 1; | 239 | sb->s_time_gran = 1; |
174 | inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0); | 240 | inode = ramfs_get_inode(sb, S_IFDIR | fsi->mount_opts.mode, 0); |
175 | if (!inode) | 241 | if (!inode) { |
176 | return -ENOMEM; | 242 | err = -ENOMEM; |
243 | goto fail; | ||
244 | } | ||
177 | 245 | ||
178 | root = d_alloc_root(inode); | 246 | root = d_alloc_root(inode); |
179 | if (!root) { | 247 | if (!root) { |
180 | iput(inode); | 248 | err = -ENOMEM; |
181 | return -ENOMEM; | 249 | goto fail; |
182 | } | 250 | } |
183 | sb->s_root = root; | 251 | sb->s_root = root; |
184 | return 0; | 252 | return 0; |
253 | fail: | ||
254 | kfree(fsi); | ||
255 | iput(inode); | ||
256 | return err; | ||
185 | } | 257 | } |
186 | 258 | ||
187 | int ramfs_get_sb(struct file_system_type *fs_type, | 259 | int ramfs_get_sb(struct file_system_type *fs_type, |
@@ -197,10 +269,16 @@ static int rootfs_get_sb(struct file_system_type *fs_type, | |||
197 | mnt); | 269 | mnt); |
198 | } | 270 | } |
199 | 271 | ||
272 | static void ramfs_kill_sb(struct super_block *sb) | ||
273 | { | ||
274 | kfree(sb->s_fs_info); | ||
275 | kill_litter_super(sb); | ||
276 | } | ||
277 | |||
200 | static struct file_system_type ramfs_fs_type = { | 278 | static struct file_system_type ramfs_fs_type = { |
201 | .name = "ramfs", | 279 | .name = "ramfs", |
202 | .get_sb = ramfs_get_sb, | 280 | .get_sb = ramfs_get_sb, |
203 | .kill_sb = kill_litter_super, | 281 | .kill_sb = ramfs_kill_sb, |
204 | }; | 282 | }; |
205 | static struct file_system_type rootfs_fs_type = { | 283 | static struct file_system_type rootfs_fs_type = { |
206 | .name = "rootfs", | 284 | .name = "rootfs", |