brintos

brintos / linux-shallow public Read only

0
0
Text · 7.6 KiB · 7de92f2 Raw
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