tiny-shmem.c 3.25 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
/*
 * 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)
{
34 35
	BUG_ON(register_filesystem(&tmpfs_fs_type) != 0);

Linus Torvalds's avatar
Linus Torvalds committed
36 37 38 39
#ifdef CONFIG_TMPFS
	devfs_mk_dir("shm");
#endif
	shm_mnt = kern_mount(&tmpfs_fs_type);
40 41
	BUG_ON(IS_ERR(shm_mnt));

Linus Torvalds's avatar
Linus Torvalds committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
	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_nlink = 0;	/* It is unlinked */
85

Linus Torvalds's avatar
Linus Torvalds committed
86 87 88 89 90
	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;
91 92

	/* notify everyone as to the change of file size */
93
	error = do_truncate(dentry, size, 0, file);
94 95 96
	if (error < 0)
		goto close_file;

Linus Torvalds's avatar
Linus Torvalds committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
	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;
}
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

int shmem_mmap(struct file *file, struct vm_area_struct *vma)
{
	file_accessed(file);
#ifndef CONFIG_MMU
	return ramfs_nommu_mmap(file, vma);
#else
	return 0;
#endif
}

#ifndef CONFIG_MMU
unsigned long shmem_get_unmapped_area(struct file *file,
				      unsigned long addr,
				      unsigned long len,
				      unsigned long pgoff,
				      unsigned long flags)
{
	return ramfs_nommu_get_unmapped_area(file, addr, len, pgoff, flags);
}
#endif