Commit 14ef4d0a authored by Matt Mackall's avatar Matt Mackall Committed by Linus Torvalds

[PATCH] tiny shmem/tmpfs replacement

A patch to replace tmpfs/shmem with ramfs for systems without swap,
incorporating the suggestions from Andi and Hugh.  It uses ramfs instead.
Signed-off-by: default avatarMatt Mackall <mpm@selenic.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 59835997
......@@ -31,6 +31,7 @@
#include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/backing-dev.h>
#include <linux/ramfs.h>
#include <asm/uaccess.h>
......@@ -39,7 +40,6 @@
static struct super_operations ramfs_ops;
static struct address_space_operations ramfs_aops;
static struct file_operations ramfs_file_operations;
static struct inode_operations ramfs_file_inode_operations;
static struct inode_operations ramfs_dir_inode_operations;
......@@ -48,7 +48,7 @@ static struct backing_dev_info ramfs_backing_dev_info = {
.memory_backed = 1, /* Does not contribute to dirty memory */
};
static struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
{
struct inode * inode = new_inode(sb);
......@@ -146,7 +146,7 @@ static struct address_space_operations ramfs_aops = {
.commit_write = simple_commit_write
};
static struct file_operations ramfs_file_operations = {
struct file_operations ramfs_file_operations = {
.read = generic_file_read,
.write = generic_file_write,
.mmap = generic_file_mmap,
......@@ -199,7 +199,7 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent)
return 0;
}
static struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
return get_sb_nodev(fs_type, flags, data, ramfs_fill_super);
......
......@@ -519,13 +519,21 @@ static inline int page_mapped(struct page *page)
extern void show_free_areas(void);
struct page *shmem_nopage(struct vm_area_struct * vma,
#ifdef CONFIG_SHMEM
struct page *shmem_nopage(struct vm_area_struct *vma,
unsigned long address, int *type);
int shmem_set_policy(struct vm_area_struct *vma, struct mempolicy *new);
struct mempolicy *shmem_get_policy(struct vm_area_struct *vma,
unsigned long addr);
struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags);
int shmem_lock(struct file *file, int lock, struct user_struct *user);
#else
#define shmem_nopage filemap_nopage
#define shmem_lock(a, b) /* always in memory, no need to lock */
#define shmem_set_policy(a, b) (0)
#define shmem_get_policy(a, b) (NULL)
#endif
struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags);
int shmem_zero_setup(struct vm_area_struct *);
static inline int can_do_mlock(void)
......
#ifndef _LINUX_RAMFS_H
#define _LINUX_RAMFS_H
struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev);
struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data);
extern struct file_operations ramfs_file_operations;
extern struct vm_operations_struct generic_file_vm_ops;
#endif
......@@ -283,8 +283,22 @@ config CC_OPTIMIZE_FOR_SIZE
If unsure, say N.
config SHMEM
default y
bool "Use full shmem filesystem" if EMBEDDED && MMU
help
The shmem is an internal filesystem used to manage shared memory.
It is backed by swap and manages resource limits. It is also exported
to userspace as tmpfs if TMPFS is enabled. Disabling this
option replaces shmem and tmpfs with the much simpler ramfs code,
which may be appropriate on small systems without swap.
endmenu # General setup
config TINY_SHMEM
default !SHMEM
bool
menu "Loadable module support"
config MODULES
......
......@@ -5,7 +5,7 @@
mmu-y := nommu.o
mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \
mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
shmem.o vmalloc.o
vmalloc.o
obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
page_alloc.o page-writeback.o pdflush.o prio_tree.o \
......@@ -15,3 +15,6 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
obj-$(CONFIG_NUMA) += mempolicy.o
obj-$(CONFIG_SHMEM) += shmem.o
obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
......@@ -1488,7 +1488,7 @@ static int filemap_populate(struct vm_area_struct *vma,
return 0;
}
static struct vm_operations_struct generic_file_vm_ops = {
struct vm_operations_struct generic_file_vm_ops = {
.nopage = filemap_nopage,
.populate = filemap_populate,
};
......
/*
* tiny-shmem.c: simple shmemfs and tmpfs using ramfs code
*
* Matt Mackall <mpm@selenic.com> January, 2004
* derived from mm/shmem.c and fs/ramfs/inode.c
*
* This is intended for small system where the benefits of the full
* shmem code (swap-backed and resource-limited) are outweighed by
* their complexity. On systems without swap this code should be
* effectively equivalent, but much lighter weight.
*/
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/vfs.h>
#include <linux/mount.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/swap.h>
#include <linux/ramfs.h>
static struct file_system_type tmpfs_fs_type = {
.name = "tmpfs",
.get_sb = ramfs_get_sb,
.kill_sb = kill_litter_super,
};
static struct vfsmount *shm_mnt;
static int __init init_tmpfs(void)
{
register_filesystem(&tmpfs_fs_type);
#ifdef CONFIG_TMPFS
devfs_mk_dir("shm");
#endif
shm_mnt = kern_mount(&tmpfs_fs_type);
return 0;
}
module_init(init_tmpfs)
/*
* shmem_file_setup - get an unlinked file living in tmpfs
*
* @name: name for dentry (to be seen in /proc/<pid>/maps
* @size: size to be set for the file
*
*/
struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
{
int error;
struct file *file;
struct inode *inode;
struct dentry *dentry, *root;
struct qstr this;
if (IS_ERR(shm_mnt))
return (void *)shm_mnt;
error = -ENOMEM;
this.name = name;
this.len = strlen(name);
this.hash = 0; /* will go */
root = shm_mnt->mnt_root;
dentry = d_alloc(root, &this);
if (!dentry)
goto put_memory;
error = -ENFILE;
file = get_empty_filp();
if (!file)
goto put_dentry;
error = -ENOSPC;
inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
if (!inode)
goto close_file;
d_instantiate(dentry, inode);
inode->i_size = size;
inode->i_nlink = 0; /* It is unlinked */
file->f_vfsmnt = mntget(shm_mnt);
file->f_dentry = dentry;
file->f_mapping = inode->i_mapping;
file->f_op = &ramfs_file_operations;
file->f_mode = FMODE_WRITE | FMODE_READ;
return file;
close_file:
put_filp(file);
put_dentry:
dput(dentry);
put_memory:
return ERR_PTR(error);
}
/*
* shmem_zero_setup - setup a shared anonymous mapping
*
* @vma: the vma to be mmapped is prepared by do_mmap_pgoff
*/
int shmem_zero_setup(struct vm_area_struct *vma)
{
struct file *file;
loff_t size = vma->vm_end - vma->vm_start;
file = shmem_file_setup("dev/zero", size, vma->vm_flags);
if (IS_ERR(file))
return PTR_ERR(file);
if (vma->vm_file)
fput(vma->vm_file);
vma->vm_file = file;
vma->vm_ops = &generic_file_vm_ops;
return 0;
}
int shmem_unuse(swp_entry_t entry, struct page *page)
{
return 0;
}
EXPORT_SYMBOL(shmem_file_setup);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment