[PATCH] tiny shmem/tmpfs replacement
authorMatt Mackall <mpm@selenic.com>
Tue, 31 Aug 2004 03:34:47 +0000 (20:34 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 31 Aug 2004 03:34:47 +0000 (20:34 -0700)
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 <mpm@selenic.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

fs/ramfs/inode.c
include/linux/mm.h
include/linux/ramfs.h [new file with mode: 0644]
init/Kconfig
mm/Makefile
mm/filemap.c
mm/tiny-shmem.c [new file with mode: 0644]

index c8e04d6..fd4353f 100644 (file)
@@ -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);
index 7a47263..397236d 100644 (file)
@@ -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)
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
new file mode 100644 (file)
index 0000000..e0a4faa
--- /dev/null
@@ -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
index 1d9857d..899a912 100644 (file)
@@ -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
index 366e50d..7cea59b 100644 (file)
@@ -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
+
index 16db7c6..36e34ed 100644 (file)
@@ -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 --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
new file mode 100644 (file)
index 0000000..90abc63
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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);