Blame view
fs/ramfs/inode.c
6.91 KB
1da177e4c
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* * Resizable simple ram filesystem for Linux. * * Copyright (C) 2000 Linus Torvalds. * 2000 Transmeta Corp. * * Usage limits added by David Gibson, Linuxcare Australia. * This file is released under the GPL. */ /* * NOTE! This filesystem is probably most useful * not as a real filesystem, but as an example of * how virtual filesystems can be written. * * It doesn't get much simpler than this. Consider * that this file implements the full semantics of * a POSIX-compliant read-write filesystem. * * Note in particular how the filesystem does not * need to implement any data structures of its own * to keep track of the virtual data: using the VFS * caches is sufficient. */ |
1da177e4c
|
25 26 27 |
#include <linux/fs.h> #include <linux/pagemap.h> #include <linux/highmem.h> |
8dde0509e
|
28 |
#include <linux/time.h> |
1da177e4c
|
29 30 |
#include <linux/init.h> #include <linux/string.h> |
1da177e4c
|
31 32 |
#include <linux/backing-dev.h> #include <linux/ramfs.h> |
e8edc6e03
|
33 |
#include <linux/sched.h> |
c3b1b1cbf
|
34 |
#include <linux/parser.h> |
a7e3108cc
|
35 |
#include <linux/magic.h> |
5a0e3ad6a
|
36 |
#include <linux/slab.h> |
1da177e4c
|
37 |
#include <asm/uaccess.h> |
642fb4d1f
|
38 |
#include "internal.h" |
1da177e4c
|
39 |
|
c3b1b1cbf
|
40 |
#define RAMFS_DEFAULT_MODE 0755 |
ee9b6d61a
|
41 |
static const struct super_operations ramfs_ops; |
c5ef1c42c
|
42 |
static const struct inode_operations ramfs_dir_inode_operations; |
1da177e4c
|
43 44 |
static struct backing_dev_info ramfs_backing_dev_info = { |
d993831fa
|
45 |
.name = "ramfs", |
1da177e4c
|
46 |
.ra_pages = 0, /* No readahead */ |
e4ad08fe6
|
47 |
.capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | |
1da177e4c
|
48 49 50 |
BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY | BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP, }; |
454abafe9
|
51 |
struct inode *ramfs_get_inode(struct super_block *sb, |
632861f05
|
52 |
const struct inode *dir, umode_t mode, dev_t dev) |
1da177e4c
|
53 54 55 56 |
{ struct inode * inode = new_inode(sb); if (inode) { |
85fe4025c
|
57 |
inode->i_ino = get_next_ino(); |
454abafe9
|
58 |
inode_init_owner(inode, dir, mode); |
1da177e4c
|
59 60 |
inode->i_mapping->a_ops = &ramfs_aops; inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info; |
769848c03
|
61 |
mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER); |
ba9ddf493
|
62 |
mapping_set_unevictable(inode->i_mapping); |
1da177e4c
|
63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; switch (mode & S_IFMT) { default: init_special_inode(inode, mode, dev); break; case S_IFREG: inode->i_op = &ramfs_file_inode_operations; inode->i_fop = &ramfs_file_operations; break; case S_IFDIR: inode->i_op = &ramfs_dir_inode_operations; inode->i_fop = &simple_dir_operations; /* directory inodes start off with i_nlink == 2 (for "." entry) */ |
d8c76e6f4
|
77 |
inc_nlink(inode); |
1da177e4c
|
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
break; case S_IFLNK: inode->i_op = &page_symlink_inode_operations; break; } } return inode; } /* * File creation. Allocate an inode, and we're done.. */ /* SMP-safe */ static int |
1a67aafb5
|
92 |
ramfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) |
1da177e4c
|
93 |
{ |
454abafe9
|
94 |
struct inode * inode = ramfs_get_inode(dir->i_sb, dir, mode, dev); |
1da177e4c
|
95 96 97 |
int error = -ENOSPC; if (inode) { |
1da177e4c
|
98 99 100 |
d_instantiate(dentry, inode); dget(dentry); /* Extra count - pin the dentry in core */ error = 0; |
8dde0509e
|
101 |
dir->i_mtime = dir->i_ctime = CURRENT_TIME; |
1da177e4c
|
102 103 104 |
} return error; } |
18bb1db3e
|
105 |
static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) |
1da177e4c
|
106 107 108 |
{ int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0); if (!retval) |
d8c76e6f4
|
109 |
inc_nlink(dir); |
1da177e4c
|
110 111 |
return retval; } |
4acdaf27e
|
112 |
static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd) |
1da177e4c
|
113 114 115 116 117 118 119 120 |
{ return ramfs_mknod(dir, dentry, mode | S_IFREG, 0); } static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) { struct inode *inode; int error = -ENOSPC; |
454abafe9
|
121 |
inode = ramfs_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0); |
1da177e4c
|
122 123 124 125 |
if (inode) { int l = strlen(symname)+1; error = page_symlink(inode, symname, l); if (!error) { |
1da177e4c
|
126 127 |
d_instantiate(dentry, inode); dget(dentry); |
ecbd3a632
|
128 |
dir->i_mtime = dir->i_ctime = CURRENT_TIME; |
1da177e4c
|
129 130 131 132 133 |
} else iput(inode); } return error; } |
c5ef1c42c
|
134 |
static const struct inode_operations ramfs_dir_inode_operations = { |
1da177e4c
|
135 136 137 138 139 140 141 142 143 144 |
.create = ramfs_create, .lookup = simple_lookup, .link = simple_link, .unlink = simple_unlink, .symlink = ramfs_symlink, .mkdir = ramfs_mkdir, .rmdir = simple_rmdir, .mknod = ramfs_mknod, .rename = simple_rename, }; |
ee9b6d61a
|
145 |
static const struct super_operations ramfs_ops = { |
1da177e4c
|
146 147 |
.statfs = simple_statfs, .drop_inode = generic_delete_inode, |
c3b1b1cbf
|
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
.show_options = generic_show_options, }; struct ramfs_mount_opts { umode_t mode; }; enum { Opt_mode, Opt_err }; static const match_table_t tokens = { {Opt_mode, "mode=%o"}, {Opt_err, NULL} }; struct ramfs_fs_info { struct ramfs_mount_opts mount_opts; |
1da177e4c
|
167 |
}; |
c3b1b1cbf
|
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
static int ramfs_parse_options(char *data, struct ramfs_mount_opts *opts) { substring_t args[MAX_OPT_ARGS]; int option; int token; char *p; opts->mode = RAMFS_DEFAULT_MODE; while ((p = strsep(&data, ",")) != NULL) { if (!*p) continue; token = match_token(p, tokens, args); switch (token) { case Opt_mode: if (match_octal(&args[0], &option)) return -EINVAL; opts->mode = option & S_IALLUGO; break; |
0a8eba9b7
|
188 189 190 191 192 193 |
/* * We might like to report bad mount options here; * but traditionally ramfs has ignored all mount options, * and as it is used as a !CONFIG_SHMEM simple substitute * for tmpfs, better continue to ignore other mount options. */ |
c3b1b1cbf
|
194 195 196 197 198 |
} } return 0; } |
da5e4ef7f
|
199 |
int ramfs_fill_super(struct super_block *sb, void *data, int silent) |
1da177e4c
|
200 |
{ |
c3b1b1cbf
|
201 202 203 204 205 206 207 208 |
struct ramfs_fs_info *fsi; struct inode *inode = NULL; struct dentry *root; int err; save_mount_options(sb, data); fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL); |
f8201abcb
|
209 |
sb->s_fs_info = fsi; |
c3b1b1cbf
|
210 211 212 213 |
if (!fsi) { err = -ENOMEM; goto fail; } |
c3b1b1cbf
|
214 215 216 217 |
err = ramfs_parse_options(data, &fsi->mount_opts); if (err) goto fail; |
1da177e4c
|
218 |
|
f8201abcb
|
219 220 221 222 223 224 |
sb->s_maxbytes = MAX_LFS_FILESIZE; sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; sb->s_magic = RAMFS_MAGIC; sb->s_op = &ramfs_ops; sb->s_time_gran = 1; |
454abafe9
|
225 |
inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0); |
c3b1b1cbf
|
226 227 228 229 |
if (!inode) { err = -ENOMEM; goto fail; } |
1da177e4c
|
230 231 |
root = d_alloc_root(inode); |
f8201abcb
|
232 |
sb->s_root = root; |
1da177e4c
|
233 |
if (!root) { |
c3b1b1cbf
|
234 235 |
err = -ENOMEM; goto fail; |
1da177e4c
|
236 |
} |
f8201abcb
|
237 |
|
1da177e4c
|
238 |
return 0; |
c3b1b1cbf
|
239 240 |
fail: kfree(fsi); |
f8201abcb
|
241 |
sb->s_fs_info = NULL; |
c3b1b1cbf
|
242 243 |
iput(inode); return err; |
1da177e4c
|
244 |
} |
3c26ff6e4
|
245 246 |
struct dentry *ramfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) |
1da177e4c
|
247 |
{ |
3c26ff6e4
|
248 |
return mount_nodev(fs_type, flags, data, ramfs_fill_super); |
1da177e4c
|
249 |
} |
3c26ff6e4
|
250 251 |
static struct dentry *rootfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) |
1da177e4c
|
252 |
{ |
3c26ff6e4
|
253 |
return mount_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super); |
1da177e4c
|
254 |
} |
c3b1b1cbf
|
255 256 257 258 259 |
static void ramfs_kill_sb(struct super_block *sb) { kfree(sb->s_fs_info); kill_litter_super(sb); } |
1da177e4c
|
260 261 |
static struct file_system_type ramfs_fs_type = { .name = "ramfs", |
3c26ff6e4
|
262 |
.mount = ramfs_mount, |
c3b1b1cbf
|
263 |
.kill_sb = ramfs_kill_sb, |
1da177e4c
|
264 265 266 |
}; static struct file_system_type rootfs_fs_type = { .name = "rootfs", |
3c26ff6e4
|
267 |
.mount = rootfs_mount, |
1da177e4c
|
268 269 270 271 272 273 274 |
.kill_sb = kill_litter_super, }; static int __init init_ramfs_fs(void) { return register_filesystem(&ramfs_fs_type); } |
1da177e4c
|
275 |
module_init(init_ramfs_fs) |
1da177e4c
|
276 277 278 |
int __init init_rootfs(void) { |
e0bf68dde
|
279 280 281 282 283 284 285 286 287 288 289 |
int err; err = bdi_init(&ramfs_backing_dev_info); if (err) return err; err = register_filesystem(&rootfs_fs_type); if (err) bdi_destroy(&ramfs_backing_dev_info); return err; |
1da177e4c
|
290 |
} |