2005-04-17 02:20:36 +04:00
/*
* 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 )
{
2005-10-31 02:03:18 +03:00
BUG_ON ( register_filesystem ( & tmpfs_fs_type ) ! = 0 ) ;
2005-04-17 02:20:36 +04:00
shm_mnt = kern_mount ( & tmpfs_fs_type ) ;
2005-10-31 02:03:18 +03:00
BUG_ON ( IS_ERR ( shm_mnt ) ) ;
2005-04-17 02:20:36 +04:00
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 */
2006-01-06 11:11:42 +03:00
2006-12-08 13:37:21 +03:00
file - > f_path . mnt = mntget ( shm_mnt ) ;
file - > f_path . dentry = dentry ;
2005-04-17 02:20:36 +04:00
file - > f_mapping = inode - > i_mapping ;
file - > f_op = & ramfs_file_operations ;
file - > f_mode = FMODE_WRITE | FMODE_READ ;
2006-01-06 11:11:42 +03:00
/* notify everyone as to the change of file size */
2006-01-12 12:05:21 +03:00
error = do_truncate ( dentry , size , 0 , file ) ;
2006-01-06 11:11:42 +03:00
if ( error < 0 )
goto close_file ;
2005-04-17 02:20:36 +04:00
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 ;
}
2006-01-06 11:11:42 +03:00
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