From: Matt Mackall 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: Matt Mackall Signed-off-by: Andrew Morton --- 25-akpm/fs/ramfs/inode.c | 8 +- 25-akpm/include/linux/mm.h | 12 +++- 25-akpm/include/linux/ramfs.h | 11 +++ 25-akpm/init/Kconfig | 14 ++++ 25-akpm/mm/Makefile | 5 + 25-akpm/mm/filemap.c | 2 25-akpm/mm/tiny-shmem.c | 124 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 168 insertions(+), 8 deletions(-) diff -puN fs/ramfs/inode.c~tiny-shmem-tmpfs-replacement fs/ramfs/inode.c --- 25/fs/ramfs/inode.c~tiny-shmem-tmpfs-replacement 2004-08-30 20:31:20.539284560 -0700 +++ 25-akpm/fs/ramfs/inode.c 2004-08-30 20:31:20.554282280 -0700 @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -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_bac .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 r .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 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); diff -puN include/linux/mm.h~tiny-shmem-tmpfs-replacement include/linux/mm.h --- 25/include/linux/mm.h~tiny-shmem-tmpfs-replacement 2004-08-30 20:31:20.544283800 -0700 +++ 25-akpm/include/linux/mm.h 2004-08-30 20:31:20.555282128 -0700 @@ -519,13 +519,21 @@ static inline int page_mapped(struct pag 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) diff -puN /dev/null include/linux/ramfs.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/include/linux/ramfs.h 2004-08-30 20:31:20.555282128 -0700 @@ -0,0 +1,11 @@ +#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 diff -puN init/Kconfig~tiny-shmem-tmpfs-replacement init/Kconfig --- 25/init/Kconfig~tiny-shmem-tmpfs-replacement 2004-08-30 20:31:20.546283496 -0700 +++ 25-akpm/init/Kconfig 2004-08-30 20:31:20.556281976 -0700 @@ -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 diff -puN mm/filemap.c~tiny-shmem-tmpfs-replacement mm/filemap.c --- 25/mm/filemap.c~tiny-shmem-tmpfs-replacement 2004-08-30 20:31:20.548283192 -0700 +++ 25-akpm/mm/filemap.c 2004-08-30 20:31:20.557281824 -0700 @@ -1488,7 +1488,7 @@ repeat: 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, }; diff -puN mm/Makefile~tiny-shmem-tmpfs-replacement mm/Makefile --- 25/mm/Makefile~tiny-shmem-tmpfs-replacement 2004-08-30 20:31:20.550282888 -0700 +++ 25-akpm/mm/Makefile 2004-08-30 20:31:20.558281672 -0700 @@ -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 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 + diff -puN /dev/null mm/tiny-shmem.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/mm/tiny-shmem.c 2004-08-30 20:31:20.558281672 -0700 @@ -0,0 +1,124 @@ +/* + * tiny-shmem.c: simple shmemfs and tmpfs using ramfs code + * + * Matt Mackall 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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//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); _