diff options
Diffstat (limited to 'fs/ramfs')
-rw-r--r-- | fs/ramfs/Makefile | 7 | ||||
-rw-r--r-- | fs/ramfs/inode.c | 246 |
2 files changed, 253 insertions, 0 deletions
diff --git a/fs/ramfs/Makefile b/fs/ramfs/Makefile new file mode 100644 index 000000000000..f096f3007091 --- /dev/null +++ b/fs/ramfs/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the linux ramfs routines. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_RAMFS) += ramfs.o | ||
6 | |||
7 | ramfs-objs := inode.o | ||
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c new file mode 100644 index 000000000000..0a88917605ae --- /dev/null +++ b/fs/ramfs/inode.c | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * Resizable simple ram filesystem for Linux. | ||
3 | * | ||
4 | * Copyright (C) 2000 Linus Torvalds. | ||
5 | * 2000 Transmeta Corp. | ||
6 | * | ||
7 | * Usage limits added by David Gibson, Linuxcare Australia. | ||
8 | * This file is released under the GPL. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * NOTE! This filesystem is probably most useful | ||
13 | * not as a real filesystem, but as an example of | ||
14 | * how virtual filesystems can be written. | ||
15 | * | ||
16 | * It doesn't get much simpler than this. Consider | ||
17 | * that this file implements the full semantics of | ||
18 | * a POSIX-compliant read-write filesystem. | ||
19 | * | ||
20 | * Note in particular how the filesystem does not | ||
21 | * need to implement any data structures of its own | ||
22 | * to keep track of the virtual data: using the VFS | ||
23 | * caches is sufficient. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/fs.h> | ||
28 | #include <linux/pagemap.h> | ||
29 | #include <linux/highmem.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/string.h> | ||
32 | #include <linux/smp_lock.h> | ||
33 | #include <linux/backing-dev.h> | ||
34 | #include <linux/ramfs.h> | ||
35 | |||
36 | #include <asm/uaccess.h> | ||
37 | |||
38 | /* some random number */ | ||
39 | #define RAMFS_MAGIC 0x858458f6 | ||
40 | |||
41 | static struct super_operations ramfs_ops; | ||
42 | static struct address_space_operations ramfs_aops; | ||
43 | static struct inode_operations ramfs_file_inode_operations; | ||
44 | static struct inode_operations ramfs_dir_inode_operations; | ||
45 | |||
46 | static struct backing_dev_info ramfs_backing_dev_info = { | ||
47 | .ra_pages = 0, /* No readahead */ | ||
48 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK | | ||
49 | BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY | | ||
50 | BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP, | ||
51 | }; | ||
52 | |||
53 | struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev) | ||
54 | { | ||
55 | struct inode * inode = new_inode(sb); | ||
56 | |||
57 | if (inode) { | ||
58 | inode->i_mode = mode; | ||
59 | inode->i_uid = current->fsuid; | ||
60 | inode->i_gid = current->fsgid; | ||
61 | inode->i_blksize = PAGE_CACHE_SIZE; | ||
62 | inode->i_blocks = 0; | ||
63 | inode->i_mapping->a_ops = &ramfs_aops; | ||
64 | inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info; | ||
65 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
66 | switch (mode & S_IFMT) { | ||
67 | default: | ||
68 | init_special_inode(inode, mode, dev); | ||
69 | break; | ||
70 | case S_IFREG: | ||
71 | inode->i_op = &ramfs_file_inode_operations; | ||
72 | inode->i_fop = &ramfs_file_operations; | ||
73 | break; | ||
74 | case S_IFDIR: | ||
75 | inode->i_op = &ramfs_dir_inode_operations; | ||
76 | inode->i_fop = &simple_dir_operations; | ||
77 | |||
78 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | ||
79 | inode->i_nlink++; | ||
80 | break; | ||
81 | case S_IFLNK: | ||
82 | inode->i_op = &page_symlink_inode_operations; | ||
83 | break; | ||
84 | } | ||
85 | } | ||
86 | return inode; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * File creation. Allocate an inode, and we're done.. | ||
91 | */ | ||
92 | /* SMP-safe */ | ||
93 | static int | ||
94 | ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | ||
95 | { | ||
96 | struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev); | ||
97 | int error = -ENOSPC; | ||
98 | |||
99 | if (inode) { | ||
100 | if (dir->i_mode & S_ISGID) { | ||
101 | inode->i_gid = dir->i_gid; | ||
102 | if (S_ISDIR(mode)) | ||
103 | inode->i_mode |= S_ISGID; | ||
104 | } | ||
105 | d_instantiate(dentry, inode); | ||
106 | dget(dentry); /* Extra count - pin the dentry in core */ | ||
107 | error = 0; | ||
108 | } | ||
109 | return error; | ||
110 | } | ||
111 | |||
112 | static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) | ||
113 | { | ||
114 | int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0); | ||
115 | if (!retval) | ||
116 | dir->i_nlink++; | ||
117 | return retval; | ||
118 | } | ||
119 | |||
120 | static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) | ||
121 | { | ||
122 | return ramfs_mknod(dir, dentry, mode | S_IFREG, 0); | ||
123 | } | ||
124 | |||
125 | static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) | ||
126 | { | ||
127 | struct inode *inode; | ||
128 | int error = -ENOSPC; | ||
129 | |||
130 | inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); | ||
131 | if (inode) { | ||
132 | int l = strlen(symname)+1; | ||
133 | error = page_symlink(inode, symname, l); | ||
134 | if (!error) { | ||
135 | if (dir->i_mode & S_ISGID) | ||
136 | inode->i_gid = dir->i_gid; | ||
137 | d_instantiate(dentry, inode); | ||
138 | dget(dentry); | ||
139 | } else | ||
140 | iput(inode); | ||
141 | } | ||
142 | return error; | ||
143 | } | ||
144 | |||
145 | static struct address_space_operations ramfs_aops = { | ||
146 | .readpage = simple_readpage, | ||
147 | .prepare_write = simple_prepare_write, | ||
148 | .commit_write = simple_commit_write | ||
149 | }; | ||
150 | |||
151 | struct file_operations ramfs_file_operations = { | ||
152 | .read = generic_file_read, | ||
153 | .write = generic_file_write, | ||
154 | .mmap = generic_file_mmap, | ||
155 | .fsync = simple_sync_file, | ||
156 | .sendfile = generic_file_sendfile, | ||
157 | .llseek = generic_file_llseek, | ||
158 | }; | ||
159 | |||
160 | static struct inode_operations ramfs_file_inode_operations = { | ||
161 | .getattr = simple_getattr, | ||
162 | }; | ||
163 | |||
164 | static struct inode_operations ramfs_dir_inode_operations = { | ||
165 | .create = ramfs_create, | ||
166 | .lookup = simple_lookup, | ||
167 | .link = simple_link, | ||
168 | .unlink = simple_unlink, | ||
169 | .symlink = ramfs_symlink, | ||
170 | .mkdir = ramfs_mkdir, | ||
171 | .rmdir = simple_rmdir, | ||
172 | .mknod = ramfs_mknod, | ||
173 | .rename = simple_rename, | ||
174 | }; | ||
175 | |||
176 | static struct super_operations ramfs_ops = { | ||
177 | .statfs = simple_statfs, | ||
178 | .drop_inode = generic_delete_inode, | ||
179 | }; | ||
180 | |||
181 | static int ramfs_fill_super(struct super_block * sb, void * data, int silent) | ||
182 | { | ||
183 | struct inode * inode; | ||
184 | struct dentry * root; | ||
185 | |||
186 | sb->s_maxbytes = MAX_LFS_FILESIZE; | ||
187 | sb->s_blocksize = PAGE_CACHE_SIZE; | ||
188 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | ||
189 | sb->s_magic = RAMFS_MAGIC; | ||
190 | sb->s_op = &ramfs_ops; | ||
191 | sb->s_time_gran = 1; | ||
192 | inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0); | ||
193 | if (!inode) | ||
194 | return -ENOMEM; | ||
195 | |||
196 | root = d_alloc_root(inode); | ||
197 | if (!root) { | ||
198 | iput(inode); | ||
199 | return -ENOMEM; | ||
200 | } | ||
201 | sb->s_root = root; | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | struct super_block *ramfs_get_sb(struct file_system_type *fs_type, | ||
206 | int flags, const char *dev_name, void *data) | ||
207 | { | ||
208 | return get_sb_nodev(fs_type, flags, data, ramfs_fill_super); | ||
209 | } | ||
210 | |||
211 | static struct super_block *rootfs_get_sb(struct file_system_type *fs_type, | ||
212 | int flags, const char *dev_name, void *data) | ||
213 | { | ||
214 | return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super); | ||
215 | } | ||
216 | |||
217 | static struct file_system_type ramfs_fs_type = { | ||
218 | .name = "ramfs", | ||
219 | .get_sb = ramfs_get_sb, | ||
220 | .kill_sb = kill_litter_super, | ||
221 | }; | ||
222 | static struct file_system_type rootfs_fs_type = { | ||
223 | .name = "rootfs", | ||
224 | .get_sb = rootfs_get_sb, | ||
225 | .kill_sb = kill_litter_super, | ||
226 | }; | ||
227 | |||
228 | static int __init init_ramfs_fs(void) | ||
229 | { | ||
230 | return register_filesystem(&ramfs_fs_type); | ||
231 | } | ||
232 | |||
233 | static void __exit exit_ramfs_fs(void) | ||
234 | { | ||
235 | unregister_filesystem(&ramfs_fs_type); | ||
236 | } | ||
237 | |||
238 | module_init(init_ramfs_fs) | ||
239 | module_exit(exit_ramfs_fs) | ||
240 | |||
241 | int __init init_rootfs(void) | ||
242 | { | ||
243 | return register_filesystem(&rootfs_fs_type); | ||
244 | } | ||
245 | |||
246 | MODULE_LICENSE("GPL"); | ||