331 lines · c
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 useful13 * not as a real filesystem, but as an example of14 * how virtual filesystems can be written.15 *16 * It doesn't get much simpler than this. Consider17 * that this file implements the full semantics of18 * a POSIX-compliant read-write filesystem.19 *20 * Note in particular how the filesystem does not21 * need to implement any data structures of its own22 * to keep track of the virtual data: using the VFS23 * caches is sufficient.24 */25 26#include <linux/fs.h>27#include <linux/pagemap.h>28#include <linux/highmem.h>29#include <linux/time.h>30#include <linux/init.h>31#include <linux/string.h>32#include <linux/backing-dev.h>33#include <linux/ramfs.h>34#include <linux/sched.h>35#include <linux/parser.h>36#include <linux/magic.h>37#include <linux/slab.h>38#include <linux/uaccess.h>39#include <linux/fs_context.h>40#include <linux/fs_parser.h>41#include <linux/seq_file.h>42#include "internal.h"43 44struct ramfs_mount_opts {45 umode_t mode;46};47 48struct ramfs_fs_info {49 struct ramfs_mount_opts mount_opts;50};51 52#define RAMFS_DEFAULT_MODE 075553 54static const struct super_operations ramfs_ops;55static const struct inode_operations ramfs_dir_inode_operations;56 57struct inode *ramfs_get_inode(struct super_block *sb,58 const struct inode *dir, umode_t mode, dev_t dev)59{60 struct inode * inode = new_inode(sb);61 62 if (inode) {63 inode->i_ino = get_next_ino();64 inode_init_owner(&nop_mnt_idmap, inode, dir, mode);65 inode->i_mapping->a_ops = &ram_aops;66 mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);67 mapping_set_unevictable(inode->i_mapping);68 simple_inode_init_ts(inode);69 switch (mode & S_IFMT) {70 default:71 init_special_inode(inode, mode, dev);72 break;73 case S_IFREG:74 inode->i_op = &ramfs_file_inode_operations;75 inode->i_fop = &ramfs_file_operations;76 break;77 case S_IFDIR:78 inode->i_op = &ramfs_dir_inode_operations;79 inode->i_fop = &simple_dir_operations;80 81 /* directory inodes start off with i_nlink == 2 (for "." entry) */82 inc_nlink(inode);83 break;84 case S_IFLNK:85 inode->i_op = &page_symlink_inode_operations;86 inode_nohighmem(inode);87 break;88 }89 }90 return inode;91}92 93/*94 * File creation. Allocate an inode, and we're done..95 */96/* SMP-safe */97static HWJS_SUSPENDS int98ramfs_mknod(struct mnt_idmap *idmap, struct inode *dir,99 struct dentry *dentry, umode_t mode, dev_t dev)100{101 struct inode * inode = ramfs_get_inode(dir->i_sb, dir, mode, dev);102 int error = -ENOSPC;103 104 if (inode) {105 error = security_inode_init_security(inode, dir,106 &dentry->d_name, NULL,107 NULL);108 if (error) {109 iput(inode);110 goto out;111 }112 113 d_instantiate(dentry, inode);114 dget(dentry); /* Extra count - pin the dentry in core */115 error = 0;116 inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir));117 }118out:119 return error;120}121 122static HWJS_SUSPENDS int ramfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,123 struct dentry *dentry, umode_t mode)124{125 int retval = ramfs_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFDIR, 0);126 if (!retval)127 inc_nlink(dir);128 return retval;129}130 131static HWJS_SUSPENDS int ramfs_create(struct mnt_idmap *idmap, struct inode *dir,132 struct dentry *dentry, umode_t mode, bool excl)133{134 return ramfs_mknod(&nop_mnt_idmap, dir, dentry, mode | S_IFREG, 0);135}136 137static HWJS_SUSPENDS int ramfs_symlink(struct mnt_idmap *idmap, struct inode *dir,138 struct dentry *dentry, const char *symname)139{140 struct inode *inode;141 int error = -ENOSPC;142 143 inode = ramfs_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0);144 if (inode) {145 int l = strlen(symname)+1;146 147 error = security_inode_init_security(inode, dir,148 &dentry->d_name, NULL,149 NULL);150 if (error) {151 iput(inode);152 goto out;153 }154 155 error = page_symlink(inode, symname, l);156 if (!error) {157 d_instantiate(dentry, inode);158 dget(dentry);159 inode_set_mtime_to_ts(dir,160 inode_set_ctime_current(dir));161 } else162 iput(inode);163 }164out:165 return error;166}167 168static HWJS_SUSPENDS int ramfs_tmpfile(struct mnt_idmap *idmap,169 struct inode *dir, struct file *file, umode_t mode)170{171 struct inode *inode;172 int error;173 174 inode = ramfs_get_inode(dir->i_sb, dir, mode, 0);175 if (!inode)176 return -ENOSPC;177 178 error = security_inode_init_security(inode, dir,179 &file_dentry(file)->d_name, NULL,180 NULL);181 if (error) {182 iput(inode);183 goto out;184 }185 186 d_tmpfile(file, inode);187out:188 return finish_open_simple(file, error);189}190 191static const struct inode_operations ramfs_dir_inode_operations = {192 .create = ramfs_create,193 .lookup = simple_lookup,194 .link = simple_link,195 .unlink = simple_unlink,196 .symlink = ramfs_symlink,197 .mkdir = ramfs_mkdir,198 .rmdir = simple_rmdir,199 .mknod = ramfs_mknod,200 .rename = simple_rename,201 .tmpfile = ramfs_tmpfile,202};203 204/*205 * Display the mount options in /proc/mounts.206 */207static int ramfs_show_options(struct seq_file *m, struct dentry *root)208{209 struct ramfs_fs_info *fsi = root->d_sb->s_fs_info;210 211 if (fsi->mount_opts.mode != RAMFS_DEFAULT_MODE)212 seq_printf(m, ",mode=%o", fsi->mount_opts.mode);213 return 0;214}215 216static const struct super_operations ramfs_ops = {217 .statfs = simple_statfs,218 .drop_inode = generic_delete_inode,219 .show_options = ramfs_show_options,220};221 222enum ramfs_param {223 Opt_mode,224};225 226const struct fs_parameter_spec ramfs_fs_parameters[] = {227 fsparam_u32oct("mode", Opt_mode),228 {}229};230 231static int ramfs_parse_param(struct fs_context *fc, struct fs_parameter *param)232{233 struct fs_parse_result result;234 struct ramfs_fs_info *fsi = fc->s_fs_info;235 int opt;236 237 opt = fs_parse(fc, ramfs_fs_parameters, param, &result);238 if (opt == -ENOPARAM) {239 opt = vfs_parse_fs_param_source(fc, param);240 if (opt != -ENOPARAM)241 return opt;242 /*243 * We might like to report bad mount options here;244 * but traditionally ramfs has ignored all mount options,245 * and as it is used as a !CONFIG_SHMEM simple substitute246 * for tmpfs, better continue to ignore other mount options.247 */248 return 0;249 }250 if (opt < 0)251 return opt;252 253 switch (opt) {254 case Opt_mode:255 fsi->mount_opts.mode = result.uint_32 & S_IALLUGO;256 break;257 }258 259 return 0;260}261 262static int ramfs_fill_super(struct super_block *sb, struct fs_context *fc)263{264 struct ramfs_fs_info *fsi = sb->s_fs_info;265 struct inode *inode;266 267 sb->s_maxbytes = MAX_LFS_FILESIZE;268 sb->s_blocksize = PAGE_SIZE;269 sb->s_blocksize_bits = PAGE_SHIFT;270 sb->s_magic = RAMFS_MAGIC;271 sb->s_op = &ramfs_ops;272 sb->s_time_gran = 1;273 274 inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0);275 sb->s_root = d_make_root(inode);276 if (!sb->s_root)277 return -ENOMEM;278 279 return 0;280}281 282static HWJS_SUSPENDS int ramfs_get_tree(struct fs_context *fc)283{284 return get_tree_nodev(fc, ramfs_fill_super);285}286 287static void ramfs_free_fc(struct fs_context *fc)288{289 kfree(fc->s_fs_info);290}291 292static const struct fs_context_operations ramfs_context_ops = {293 .free = ramfs_free_fc,294 .parse_param = ramfs_parse_param,295 .get_tree = ramfs_get_tree,296};297 298int ramfs_init_fs_context(struct fs_context *fc)299{300 struct ramfs_fs_info *fsi;301 302 fsi = kzalloc(sizeof(*fsi), GFP_KERNEL);303 if (!fsi)304 return -ENOMEM;305 306 fsi->mount_opts.mode = RAMFS_DEFAULT_MODE;307 fc->s_fs_info = fsi;308 fc->ops = &ramfs_context_ops;309 return 0;310}311 312void ramfs_kill_sb(struct super_block *sb)313{314 kfree(sb->s_fs_info);315 kill_litter_super(sb);316}317 318static struct file_system_type ramfs_fs_type = {319 .name = "ramfs",320 .init_fs_context = ramfs_init_fs_context,321 .parameters = ramfs_fs_parameters,322 .kill_sb = ramfs_kill_sb,323 .fs_flags = FS_USERNS_MOUNT,324};325 326static int __init init_ramfs_fs(void)327{328 return register_filesystem(&ramfs_fs_type);329}330fs_initcall(init_ramfs_fs);331