11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Resizable simple ram filesystem for Linux. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2000 Linus Torvalds. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000 Transmeta Corp. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Usage limits added by David Gibson, Linuxcare Australia. 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is released under the GPL. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE! This filesystem is probably most useful 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * not as a real filesystem, but as an example of 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * how virtual filesystems can be written. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It doesn't get much simpler than this. Consider 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that this file implements the full semantics of 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a POSIX-compliant read-write filesystem. 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note in particular how the filesystem does not 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need to implement any data structures of its own 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to keep track of the virtual data: using the VFS 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * caches is sufficient. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pagemap.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/highmem.h> 298dde0509e74ff6044cf1788c917a22facce9f68dAndrew Morton#include <linux/time.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/backing-dev.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ramfs.h> 34e8edc6e03a5c8562dc70a6d969f732bdb355a7e7Alexey Dobriyan#include <linux/sched.h> 35c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang#include <linux/parser.h> 36a7e3108cca54c105f496919040f00df56767ec00maximilian attems#include <linux/magic.h> 375a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 39642fb4d1f1dd2417aa69189fe5ceb81e4fb72900David Howells#include "internal.h" 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang#define RAMFS_DEFAULT_MODE 0755 42c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 43ee9b6d61a2a43c5952eb43283f8db284a4e70b8aJosef 'Jeff' Sipekstatic const struct super_operations ramfs_ops; 44c5ef1c42c51b1b5b4a401a6517bdda30933ddbafArjan van de Venstatic const struct inode_operations ramfs_dir_inode_operations; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4687e06aa3a7e5f9fbc2f5215c4ba9c4a42b404192Axel Linstatic const struct address_space_operations ramfs_aops = { 4787e06aa3a7e5f9fbc2f5215c4ba9c4a42b404192Axel Lin .readpage = simple_readpage, 4887e06aa3a7e5f9fbc2f5215c4ba9c4a42b404192Axel Lin .write_begin = simple_write_begin, 4987e06aa3a7e5f9fbc2f5215c4ba9c4a42b404192Axel Lin .write_end = simple_write_end, 5087e06aa3a7e5f9fbc2f5215c4ba9c4a42b404192Axel Lin .set_page_dirty = __set_page_dirty_no_writeback, 5187e06aa3a7e5f9fbc2f5215c4ba9c4a42b404192Axel Lin}; 5287e06aa3a7e5f9fbc2f5215c4ba9c4a42b404192Axel Lin 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct backing_dev_info ramfs_backing_dev_info = { 54d993831fa7ffeb89e994f046f93eeb09ec91df08Jens Axboe .name = "ramfs", 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .ra_pages = 0, /* No readahead */ 56e4ad08fe64afca4ef79ecc4c624e6e871688da0dMiklos Szeredi .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK | 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY | 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP, 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61454abafe9d8beb3fe7da06131b3d81d6d352a959Dmitry Monakhovstruct inode *ramfs_get_inode(struct super_block *sb, 62632861f05a8e5878a267d173000880ceb608b56eAl Viro const struct inode *dir, umode_t mode, dev_t dev) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct inode * inode = new_inode(sb); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inode) { 6785fe4025c616a7c0ed07bc2fc8c5371b07f3888cChristoph Hellwig inode->i_ino = get_next_ino(); 68454abafe9d8beb3fe7da06131b3d81d6d352a959Dmitry Monakhov inode_init_owner(inode, dir, mode); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inode->i_mapping->a_ops = &ramfs_aops; 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info; 71769848c03895b63e5662eb7e4ec8c4866f7d0183Mel Gorman mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER); 72ba9ddf49391645e6bb93219131a40446538a5e76Lee Schermerhorn mapping_set_unevictable(inode->i_mapping); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (mode & S_IFMT) { 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_special_inode(inode, mode, dev); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case S_IFREG: 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inode->i_op = &ramfs_file_inode_operations; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inode->i_fop = &ramfs_file_operations; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case S_IFDIR: 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inode->i_op = &ramfs_dir_inode_operations; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inode->i_fop = &simple_dir_operations; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* directory inodes start off with i_nlink == 2 (for "." entry) */ 87d8c76e6f45c111c32a4b3e50a2adc9210737b0d8Dave Hansen inc_nlink(inode); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case S_IFLNK: 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inode->i_op = &page_symlink_inode_operations; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return inode; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * File creation. Allocate an inode, and we're done.. 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SMP-safe */ 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1021a67aafb5f72a436ca044293309fa7e6351d6a35Al Viroramfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 104454abafe9d8beb3fe7da06131b3d81d6d352a959Dmitry Monakhov struct inode * inode = ramfs_get_inode(dir->i_sb, dir, mode, dev); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = -ENOSPC; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inode) { 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d_instantiate(dentry, inode); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dget(dentry); /* Extra count - pin the dentry in core */ 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = 0; 1118dde0509e74ff6044cf1788c917a22facce9f68dAndrew Morton dir->i_mtime = dir->i_ctime = CURRENT_TIME; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11618bb1db3e7607e4a997d50991a6f9fa5b0f8722cAl Virostatic int ramfs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!retval) 120d8c76e6f45c111c32a4b3e50a2adc9210737b0d8Dave Hansen inc_nlink(dir); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 124ebfc3b49a7ac25920cb5be5445f602e51d2ea559Al Virostatic int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ramfs_mknod(dir, dentry, mode | S_IFREG, 0); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct inode *inode; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = -ENOSPC; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 134454abafe9d8beb3fe7da06131b3d81d6d352a959Dmitry Monakhov inode = ramfs_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inode) { 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int l = strlen(symname)+1; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds error = page_symlink(inode, symname, l); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!error) { 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d_instantiate(dentry, inode); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dget(dentry); 141ecbd3a632c8198744655b769c5c2b5a1455c1fbaPeter Staubach dir->i_mtime = dir->i_ctime = CURRENT_TIME; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iput(inode); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return error; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 148c5ef1c42c51b1b5b4a401a6517bdda30933ddbafArjan van de Venstatic const struct inode_operations ramfs_dir_inode_operations = { 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .create = ramfs_create, 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lookup = simple_lookup, 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .link = simple_link, 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unlink = simple_unlink, 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .symlink = ramfs_symlink, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mkdir = ramfs_mkdir, 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .rmdir = simple_rmdir, 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mknod = ramfs_mknod, 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .rename = simple_rename, 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 160ee9b6d61a2a43c5952eb43283f8db284a4e70b8aJosef 'Jeff' Sipekstatic const struct super_operations ramfs_ops = { 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .statfs = simple_statfs, 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .drop_inode = generic_delete_inode, 163c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang .show_options = generic_show_options, 164c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang}; 165c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 166c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguangstruct ramfs_mount_opts { 167c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang umode_t mode; 168c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang}; 169c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 170c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguangenum { 171c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang Opt_mode, 172c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang Opt_err 173c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang}; 174c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 175c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguangstatic const match_table_t tokens = { 176c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang {Opt_mode, "mode=%o"}, 177c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang {Opt_err, NULL} 178c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang}; 179c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 180c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguangstruct ramfs_fs_info { 181c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang struct ramfs_mount_opts mount_opts; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 184c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguangstatic int ramfs_parse_options(char *data, struct ramfs_mount_opts *opts) 185c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang{ 186c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang substring_t args[MAX_OPT_ARGS]; 187c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang int option; 188c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang int token; 189c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang char *p; 190c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 191c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang opts->mode = RAMFS_DEFAULT_MODE; 192c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 193c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang while ((p = strsep(&data, ",")) != NULL) { 194c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang if (!*p) 195c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang continue; 196c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 197c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang token = match_token(p, tokens, args); 198c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang switch (token) { 199c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang case Opt_mode: 200c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang if (match_octal(&args[0], &option)) 201c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang return -EINVAL; 202c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang opts->mode = option & S_IALLUGO; 203c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang break; 2040a8eba9b7f7aa3ad0305627c99ad4d6deedd871dMike Frysinger /* 2050a8eba9b7f7aa3ad0305627c99ad4d6deedd871dMike Frysinger * We might like to report bad mount options here; 2060a8eba9b7f7aa3ad0305627c99ad4d6deedd871dMike Frysinger * but traditionally ramfs has ignored all mount options, 2070a8eba9b7f7aa3ad0305627c99ad4d6deedd871dMike Frysinger * and as it is used as a !CONFIG_SHMEM simple substitute 2080a8eba9b7f7aa3ad0305627c99ad4d6deedd871dMike Frysinger * for tmpfs, better continue to ignore other mount options. 2090a8eba9b7f7aa3ad0305627c99ad4d6deedd871dMike Frysinger */ 210c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang } 211c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang } 212c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 213c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang return 0; 214c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang} 215c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 216da5e4ef7fdb8f2fb0878dee3bd9d4dd10cea8cf1Peter Korsgaardint ramfs_fill_super(struct super_block *sb, void *data, int silent) 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 218c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang struct ramfs_fs_info *fsi; 219318ceed088497d1ca839b1172518ac4cc7096b82Al Viro struct inode *inode; 220c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang int err; 221c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 222c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang save_mount_options(sb, data); 223c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 224c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL); 225f8201abcb2badce7eaa6a3715f9a228cfd88a453Ingo Molnar sb->s_fs_info = fsi; 226318ceed088497d1ca839b1172518ac4cc7096b82Al Viro if (!fsi) 227318ceed088497d1ca839b1172518ac4cc7096b82Al Viro return -ENOMEM; 228c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 229c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang err = ramfs_parse_options(data, &fsi->mount_opts); 230c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang if (err) 231318ceed088497d1ca839b1172518ac4cc7096b82Al Viro return err; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 233f8201abcb2badce7eaa6a3715f9a228cfd88a453Ingo Molnar sb->s_maxbytes = MAX_LFS_FILESIZE; 234f8201abcb2badce7eaa6a3715f9a228cfd88a453Ingo Molnar sb->s_blocksize = PAGE_CACHE_SIZE; 235f8201abcb2badce7eaa6a3715f9a228cfd88a453Ingo Molnar sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 236f8201abcb2badce7eaa6a3715f9a228cfd88a453Ingo Molnar sb->s_magic = RAMFS_MAGIC; 237f8201abcb2badce7eaa6a3715f9a228cfd88a453Ingo Molnar sb->s_op = &ramfs_ops; 238f8201abcb2badce7eaa6a3715f9a228cfd88a453Ingo Molnar sb->s_time_gran = 1; 239f8201abcb2badce7eaa6a3715f9a228cfd88a453Ingo Molnar 240454abafe9d8beb3fe7da06131b3d81d6d352a959Dmitry Monakhov inode = ramfs_get_inode(sb, NULL, S_IFDIR | fsi->mount_opts.mode, 0); 24148fde701aff662559b38d9a609574068f22d00feAl Viro sb->s_root = d_make_root(inode); 242318ceed088497d1ca839b1172518ac4cc7096b82Al Viro if (!sb->s_root) 243318ceed088497d1ca839b1172518ac4cc7096b82Al Viro return -ENOMEM; 244f8201abcb2badce7eaa6a3715f9a228cfd88a453Ingo Molnar 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2483c26ff6e499ee7e6f9f2bc7da5f2f30d80862ecfAl Virostruct dentry *ramfs_mount(struct file_system_type *fs_type, 2493c26ff6e499ee7e6f9f2bc7da5f2f30d80862ecfAl Viro int flags, const char *dev_name, void *data) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2513c26ff6e499ee7e6f9f2bc7da5f2f30d80862ecfAl Viro return mount_nodev(fs_type, flags, data, ramfs_fill_super); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 254c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguangstatic void ramfs_kill_sb(struct super_block *sb) 255c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang{ 256c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang kfree(sb->s_fs_info); 257c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang kill_litter_super(sb); 258c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang} 259c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct file_system_type ramfs_fs_type = { 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "ramfs", 2623c26ff6e499ee7e6f9f2bc7da5f2f30d80862ecfAl Viro .mount = ramfs_mount, 263c3b1b1cbf002e65a3cabd479e68b5f35886a26dbWu Fengguang .kill_sb = ramfs_kill_sb, 264b3c6761d9b5cc82deea7416d11c2118f6380e99cEric W. Biederman .fs_flags = FS_USERNS_MOUNT, 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26757f150a58c40cda598c31af8bceb8598f43c3e5fRob Landleyint __init init_ramfs_fs(void) 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2694bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley static unsigned long once; 2704bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley int err; 2714bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley 2724bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley if (test_and_set_bit(0, &once)) 2734bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley return 0; 2744bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley 2754bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley err = bdi_init(&ramfs_backing_dev_info); 2764bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley if (err) 2774bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley return err; 2784bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley 2794bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley err = register_filesystem(&ramfs_fs_type); 2804bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley if (err) 2814bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley bdi_destroy(&ramfs_backing_dev_info); 2824bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley 2834bbee76bc986af326be0a84ad661000cf89b29f6Rob Landley return err; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 285af52b040eba5e6982d8665af8cd4dd69a466d5c3Paul Gortmakerfs_initcall(init_ramfs_fs); 286