150 lines · 3.2 KB · C
RawDownload
/* * 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/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){	BUG_ON(register_filesystem(&tmpfs_fs_type) != 0); 	shm_mnt = kern_mount(&tmpfs_fs_type);	BUG_ON(IS_ERR(shm_mnt)); 	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 */ 	file->f_path.mnt = mntget(shm_mnt);	file->f_path.dentry = dentry;	file->f_mapping = inode->i_mapping;	file->f_op = &ramfs_file_operations;	file->f_mode = FMODE_WRITE | FMODE_READ; 	/* notify everyone as to the change of file size */	error = do_truncate(dentry, size, 0, file);	if (error < 0)		goto close_file; 	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;} #if 0int 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}#endif  /*  0  */ #ifndef CONFIG_MMUunsigned 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