2005-04-17 02:20:36 +04:00
/*
* linux / fs / minix / inode . c
*
* Copyright ( C ) 1991 , 1992 Linus Torvalds
*
2009-03-22 01:18:57 +03:00
* Copyright ( C ) 1996 Gertjan van Wingerde
2005-04-17 02:20:36 +04:00
* Minix V2 fs support .
*
* Modified for 680 x0 by Andreas Schwab
2007-02-12 11:52:49 +03:00
* Updated to filesystem version 3 by Daniel Aragones
2005-04-17 02:20:36 +04:00
*/
# include <linux/module.h>
# include "minix.h"
# include <linux/buffer_head.h>
# include <linux/slab.h>
# include <linux/init.h>
# include <linux/highuid.h>
# include <linux/vfs.h>
2010-03-05 11:21:37 +03:00
# include <linux/writeback.h>
2005-04-17 02:20:36 +04:00
2010-03-05 11:21:37 +03:00
static int minix_write_inode ( struct inode * inode ,
struct writeback_control * wbc ) ;
2006-06-23 13:02:58 +04:00
static int minix_statfs ( struct dentry * dentry , struct kstatfs * buf ) ;
2005-04-17 02:20:36 +04:00
static int minix_remount ( struct super_block * sb , int * flags , char * data ) ;
2010-06-05 06:27:38 +04:00
static void minix_evict_inode ( struct inode * inode )
2005-04-17 02:20:36 +04:00
{
2005-09-10 00:01:31 +04:00
truncate_inode_pages ( & inode - > i_data , 0 ) ;
2010-06-05 06:27:38 +04:00
if ( ! inode - > i_nlink ) {
inode - > i_size = 0 ;
minix_truncate ( inode ) ;
}
invalidate_inode_buffers ( inode ) ;
end_writeback ( inode ) ;
if ( ! inode - > i_nlink )
minix_free_inode ( inode ) ;
2005-04-17 02:20:36 +04:00
}
static void minix_put_super ( struct super_block * sb )
{
int i ;
struct minix_sb_info * sbi = minix_sb ( sb ) ;
if ( ! ( sb - > s_flags & MS_RDONLY ) ) {
2007-02-12 11:52:49 +03:00
if ( sbi - > s_version ! = MINIX_V3 ) /* s_state is now out from V3 sb */
sbi - > s_ms - > s_state = sbi - > s_mount_state ;
2005-04-17 02:20:36 +04:00
mark_buffer_dirty ( sbi - > s_sbh ) ;
}
for ( i = 0 ; i < sbi - > s_imap_blocks ; i + + )
brelse ( sbi - > s_imap [ i ] ) ;
for ( i = 0 ; i < sbi - > s_zmap_blocks ; i + + )
brelse ( sbi - > s_zmap [ i ] ) ;
brelse ( sbi - > s_sbh ) ;
kfree ( sbi - > s_imap ) ;
sb - > s_fs_info = NULL ;
kfree ( sbi ) ;
}
2006-12-07 07:33:20 +03:00
static struct kmem_cache * minix_inode_cachep ;
2005-04-17 02:20:36 +04:00
static struct inode * minix_alloc_inode ( struct super_block * sb )
{
struct minix_inode_info * ei ;
2006-12-07 07:33:17 +03:00
ei = ( struct minix_inode_info * ) kmem_cache_alloc ( minix_inode_cachep , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! ei )
return NULL ;
return & ei - > vfs_inode ;
}
2011-01-07 09:49:49 +03:00
static void minix_i_callback ( struct rcu_head * head )
2005-04-17 02:20:36 +04:00
{
2011-01-07 09:49:49 +03:00
struct inode * inode = container_of ( head , struct inode , i_rcu ) ;
INIT_LIST_HEAD ( & inode - > i_dentry ) ;
2005-04-17 02:20:36 +04:00
kmem_cache_free ( minix_inode_cachep , minix_i ( inode ) ) ;
}
2011-01-07 09:49:49 +03:00
static void minix_destroy_inode ( struct inode * inode )
{
call_rcu ( & inode - > i_rcu , minix_i_callback ) ;
}
2008-07-26 06:45:34 +04:00
static void init_once ( void * foo )
2005-04-17 02:20:36 +04:00
{
struct minix_inode_info * ei = ( struct minix_inode_info * ) foo ;
2007-05-17 09:10:57 +04:00
inode_init_once ( & ei - > vfs_inode ) ;
2005-04-17 02:20:36 +04:00
}
2007-07-20 05:11:58 +04:00
2005-04-17 02:20:36 +04:00
static int init_inodecache ( void )
{
minix_inode_cachep = kmem_cache_create ( " minix_inode_cache " ,
sizeof ( struct minix_inode_info ) ,
2006-03-24 14:16:06 +03:00
0 , ( SLAB_RECLAIM_ACCOUNT |
SLAB_MEM_SPREAD ) ,
2007-07-20 05:11:58 +04:00
init_once ) ;
2005-04-17 02:20:36 +04:00
if ( minix_inode_cachep = = NULL )
return - ENOMEM ;
return 0 ;
}
static void destroy_inodecache ( void )
{
2006-09-27 12:49:40 +04:00
kmem_cache_destroy ( minix_inode_cachep ) ;
2005-04-17 02:20:36 +04:00
}
2007-02-12 11:55:41 +03:00
static const struct super_operations minix_sops = {
2005-04-17 02:20:36 +04:00
. alloc_inode = minix_alloc_inode ,
. destroy_inode = minix_destroy_inode ,
. write_inode = minix_write_inode ,
2010-06-05 06:27:38 +04:00
. evict_inode = minix_evict_inode ,
2005-04-17 02:20:36 +04:00
. put_super = minix_put_super ,
. statfs = minix_statfs ,
. remount_fs = minix_remount ,
} ;
static int minix_remount ( struct super_block * sb , int * flags , char * data )
{
struct minix_sb_info * sbi = minix_sb ( sb ) ;
struct minix_super_block * ms ;
ms = sbi - > s_ms ;
if ( ( * flags & MS_RDONLY ) = = ( sb - > s_flags & MS_RDONLY ) )
return 0 ;
if ( * flags & MS_RDONLY ) {
if ( ms - > s_state & MINIX_VALID_FS | |
! ( sbi - > s_mount_state & MINIX_VALID_FS ) )
return 0 ;
/* Mounting a rw partition read-only. */
2007-02-12 11:52:49 +03:00
if ( sbi - > s_version ! = MINIX_V3 )
ms - > s_state = sbi - > s_mount_state ;
2005-04-17 02:20:36 +04:00
mark_buffer_dirty ( sbi - > s_sbh ) ;
} else {
/* Mount a partition which is read-only, read-write. */
2007-02-12 11:52:49 +03:00
if ( sbi - > s_version ! = MINIX_V3 ) {
sbi - > s_mount_state = ms - > s_state ;
ms - > s_state & = ~ MINIX_VALID_FS ;
} else {
sbi - > s_mount_state = MINIX_VALID_FS ;
}
2005-04-17 02:20:36 +04:00
mark_buffer_dirty ( sbi - > s_sbh ) ;
if ( ! ( sbi - > s_mount_state & MINIX_VALID_FS ) )
2006-03-25 14:07:42 +03:00
printk ( " MINIX-fs warning: remounting unchecked fs, "
" running fsck is recommended \n " ) ;
2005-04-17 02:20:36 +04:00
else if ( ( sbi - > s_mount_state & MINIX_ERROR_FS ) )
2006-03-25 14:07:42 +03:00
printk ( " MINIX-fs warning: remounting fs with errors, "
" running fsck is recommended \n " ) ;
2005-04-17 02:20:36 +04:00
}
return 0 ;
}
static int minix_fill_super ( struct super_block * s , void * data , int silent )
{
struct buffer_head * bh ;
struct buffer_head * * map ;
struct minix_super_block * ms ;
2007-02-12 11:52:49 +03:00
struct minix3_super_block * m3s = NULL ;
unsigned long i , block ;
2005-04-17 02:20:36 +04:00
struct inode * root_inode ;
struct minix_sb_info * sbi ;
2008-02-07 11:15:44 +03:00
int ret = - EINVAL ;
2005-04-17 02:20:36 +04:00
2006-09-27 12:49:37 +04:00
sbi = kzalloc ( sizeof ( struct minix_sb_info ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! sbi )
return - ENOMEM ;
s - > s_fs_info = sbi ;
2006-10-11 12:22:05 +04:00
BUILD_BUG_ON ( 32 ! = sizeof ( struct minix_inode ) ) ;
BUILD_BUG_ON ( 64 ! = sizeof ( struct minix2_inode ) ) ;
2005-04-17 02:20:36 +04:00
if ( ! sb_set_blocksize ( s , BLOCK_SIZE ) )
goto out_bad_hblock ;
if ( ! ( bh = sb_bread ( s , 1 ) ) )
goto out_bad_sb ;
ms = ( struct minix_super_block * ) bh - > b_data ;
sbi - > s_ms = ms ;
sbi - > s_sbh = bh ;
sbi - > s_mount_state = ms - > s_state ;
sbi - > s_ninodes = ms - > s_ninodes ;
sbi - > s_nzones = ms - > s_nzones ;
sbi - > s_imap_blocks = ms - > s_imap_blocks ;
sbi - > s_zmap_blocks = ms - > s_zmap_blocks ;
sbi - > s_firstdatazone = ms - > s_firstdatazone ;
sbi - > s_log_zone_size = ms - > s_log_zone_size ;
sbi - > s_max_size = ms - > s_max_size ;
s - > s_magic = ms - > s_magic ;
if ( s - > s_magic = = MINIX_SUPER_MAGIC ) {
sbi - > s_version = MINIX_V1 ;
sbi - > s_dirsize = 16 ;
sbi - > s_namelen = 14 ;
sbi - > s_link_max = MINIX_LINK_MAX ;
} else if ( s - > s_magic = = MINIX_SUPER_MAGIC2 ) {
sbi - > s_version = MINIX_V1 ;
sbi - > s_dirsize = 32 ;
sbi - > s_namelen = 30 ;
sbi - > s_link_max = MINIX_LINK_MAX ;
} else if ( s - > s_magic = = MINIX2_SUPER_MAGIC ) {
sbi - > s_version = MINIX_V2 ;
sbi - > s_nzones = ms - > s_zones ;
sbi - > s_dirsize = 16 ;
sbi - > s_namelen = 14 ;
sbi - > s_link_max = MINIX2_LINK_MAX ;
} else if ( s - > s_magic = = MINIX2_SUPER_MAGIC2 ) {
sbi - > s_version = MINIX_V2 ;
sbi - > s_nzones = ms - > s_zones ;
sbi - > s_dirsize = 32 ;
sbi - > s_namelen = 30 ;
sbi - > s_link_max = MINIX2_LINK_MAX ;
2007-02-12 11:52:49 +03:00
} else if ( * ( __u16 * ) ( bh - > b_data + 24 ) = = MINIX3_SUPER_MAGIC ) {
m3s = ( struct minix3_super_block * ) bh - > b_data ;
s - > s_magic = m3s - > s_magic ;
sbi - > s_imap_blocks = m3s - > s_imap_blocks ;
sbi - > s_zmap_blocks = m3s - > s_zmap_blocks ;
sbi - > s_firstdatazone = m3s - > s_firstdatazone ;
sbi - > s_log_zone_size = m3s - > s_log_zone_size ;
sbi - > s_max_size = m3s - > s_max_size ;
sbi - > s_ninodes = m3s - > s_ninodes ;
sbi - > s_nzones = m3s - > s_zones ;
sbi - > s_dirsize = 64 ;
sbi - > s_namelen = 60 ;
sbi - > s_version = MINIX_V3 ;
sbi - > s_link_max = MINIX2_LINK_MAX ;
sbi - > s_mount_state = MINIX_VALID_FS ;
sb_set_blocksize ( s , m3s - > s_blocksize ) ;
2005-04-17 02:20:36 +04:00
} else
goto out_no_fs ;
/*
* Allocate the buffer map to keep the superblock small .
*/
2006-08-27 12:23:42 +04:00
if ( sbi - > s_imap_blocks = = 0 | | sbi - > s_zmap_blocks = = 0 )
goto out_illegal_sb ;
2005-04-17 02:20:36 +04:00
i = ( sbi - > s_imap_blocks + sbi - > s_zmap_blocks ) * sizeof ( bh ) ;
2006-09-27 12:49:37 +04:00
map = kzalloc ( i , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! map )
goto out_no_map ;
sbi - > s_imap = & map [ 0 ] ;
sbi - > s_zmap = & map [ sbi - > s_imap_blocks ] ;
block = 2 ;
for ( i = 0 ; i < sbi - > s_imap_blocks ; i + + ) {
if ( ! ( sbi - > s_imap [ i ] = sb_bread ( s , block ) ) )
goto out_no_bitmap ;
block + + ;
}
for ( i = 0 ; i < sbi - > s_zmap_blocks ; i + + ) {
if ( ! ( sbi - > s_zmap [ i ] = sb_bread ( s , block ) ) )
goto out_no_bitmap ;
block + + ;
}
minix_set_bit ( 0 , sbi - > s_imap [ 0 ] - > b_data ) ;
minix_set_bit ( 0 , sbi - > s_zmap [ 0 ] - > b_data ) ;
/* set up enough so that it can read an inode */
s - > s_op = & minix_sops ;
2008-02-07 11:15:44 +03:00
root_inode = minix_iget ( s , MINIX_ROOT_INO ) ;
if ( IS_ERR ( root_inode ) ) {
ret = PTR_ERR ( root_inode ) ;
2005-04-17 02:20:36 +04:00
goto out_no_root ;
2008-02-07 11:15:44 +03:00
}
2005-04-17 02:20:36 +04:00
2008-02-07 11:15:44 +03:00
ret = - ENOMEM ;
2005-04-17 02:20:36 +04:00
s - > s_root = d_alloc_root ( root_inode ) ;
if ( ! s - > s_root )
goto out_iput ;
if ( ! ( s - > s_flags & MS_RDONLY ) ) {
2007-02-12 11:52:49 +03:00
if ( sbi - > s_version ! = MINIX_V3 ) /* s_state is now out from V3 sb */
ms - > s_state & = ~ MINIX_VALID_FS ;
2005-04-17 02:20:36 +04:00
mark_buffer_dirty ( bh ) ;
}
if ( ! ( sbi - > s_mount_state & MINIX_VALID_FS ) )
2006-03-25 14:07:42 +03:00
printk ( " MINIX-fs: mounting unchecked file system, "
" running fsck is recommended \n " ) ;
2005-04-17 02:20:36 +04:00
else if ( sbi - > s_mount_state & MINIX_ERROR_FS )
2006-03-25 14:07:42 +03:00
printk ( " MINIX-fs: mounting file system with errors, "
" running fsck is recommended \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
out_iput :
iput ( root_inode ) ;
goto out_freemap ;
out_no_root :
if ( ! silent )
printk ( " MINIX-fs: get root inode failed \n " ) ;
goto out_freemap ;
out_no_bitmap :
printk ( " MINIX-fs: bad superblock or unable to read bitmaps \n " ) ;
2006-08-27 12:23:42 +04:00
out_freemap :
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < sbi - > s_imap_blocks ; i + + )
brelse ( sbi - > s_imap [ i ] ) ;
for ( i = 0 ; i < sbi - > s_zmap_blocks ; i + + )
brelse ( sbi - > s_zmap [ i ] ) ;
kfree ( sbi - > s_imap ) ;
goto out_release ;
out_no_map :
2008-02-07 11:15:44 +03:00
ret = - ENOMEM ;
2005-04-17 02:20:36 +04:00
if ( ! silent )
2006-03-25 14:07:42 +03:00
printk ( " MINIX-fs: can't allocate map \n " ) ;
2005-04-17 02:20:36 +04:00
goto out_release ;
2006-08-27 12:23:42 +04:00
out_illegal_sb :
if ( ! silent )
printk ( " MINIX-fs: bad superblock \n " ) ;
goto out_release ;
2005-04-17 02:20:36 +04:00
out_no_fs :
if ( ! silent )
2007-02-12 11:52:49 +03:00
printk ( " VFS: Can't find a Minix filesystem V1 | V2 | V3 "
" on device %s. \n " , s - > s_id ) ;
2006-08-27 12:23:42 +04:00
out_release :
2005-04-17 02:20:36 +04:00
brelse ( bh ) ;
goto out ;
out_bad_hblock :
2006-03-25 14:07:42 +03:00
printk ( " MINIX-fs: blocksize too small for device \n " ) ;
2005-04-17 02:20:36 +04:00
goto out ;
out_bad_sb :
printk ( " MINIX-fs: unable to read superblock \n " ) ;
2006-08-27 12:23:42 +04:00
out :
2005-04-17 02:20:36 +04:00
s - > s_fs_info = NULL ;
kfree ( sbi ) ;
2008-02-07 11:15:44 +03:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2006-06-23 13:02:58 +04:00
static int minix_statfs ( struct dentry * dentry , struct kstatfs * buf )
2005-04-17 02:20:36 +04:00
{
2009-04-03 03:59:39 +04:00
struct super_block * sb = dentry - > d_sb ;
struct minix_sb_info * sbi = minix_sb ( sb ) ;
u64 id = huge_encode_dev ( sb - > s_bdev - > bd_dev ) ;
buf - > f_type = sb - > s_magic ;
buf - > f_bsize = sb - > s_blocksize ;
2005-04-17 02:20:36 +04:00
buf - > f_blocks = ( sbi - > s_nzones - sbi - > s_firstdatazone ) < < sbi - > s_log_zone_size ;
buf - > f_bfree = minix_count_free_blocks ( sbi ) ;
buf - > f_bavail = buf - > f_bfree ;
buf - > f_files = sbi - > s_ninodes ;
buf - > f_ffree = minix_count_free_inodes ( sbi ) ;
buf - > f_namelen = sbi - > s_namelen ;
2009-04-03 03:59:39 +04:00
buf - > f_fsid . val [ 0 ] = ( u32 ) id ;
buf - > f_fsid . val [ 1 ] = ( u32 ) ( id > > 32 ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int minix_get_block ( struct inode * inode , sector_t block ,
struct buffer_head * bh_result , int create )
{
if ( INODE_VERSION ( inode ) = = MINIX_V1 )
return V1_minix_get_block ( inode , block , bh_result , create ) ;
else
return V2_minix_get_block ( inode , block , bh_result , create ) ;
}
static int minix_writepage ( struct page * page , struct writeback_control * wbc )
{
return block_write_full_page ( page , minix_get_block , wbc ) ;
}
2007-10-16 12:25:21 +04:00
2005-04-17 02:20:36 +04:00
static int minix_readpage ( struct file * file , struct page * page )
{
return block_read_full_page ( page , minix_get_block ) ;
}
2007-10-16 12:25:21 +04:00
2010-06-04 13:29:56 +04:00
int minix_prepare_chunk ( struct page * page , loff_t pos , unsigned len )
2005-04-17 02:20:36 +04:00
{
2010-06-04 13:29:57 +04:00
return __block_write_begin ( page , pos , len , minix_get_block ) ;
2005-04-17 02:20:36 +04:00
}
2007-10-16 12:25:21 +04:00
static int minix_write_begin ( struct file * file , struct address_space * mapping ,
loff_t pos , unsigned len , unsigned flags ,
struct page * * pagep , void * * fsdata )
{
2010-06-04 13:29:58 +04:00
int ret ;
ret = block_write_begin ( mapping , pos , len , flags , pagep ,
2010-06-04 13:29:56 +04:00
minix_get_block ) ;
2010-06-04 13:29:58 +04:00
if ( unlikely ( ret ) ) {
loff_t isize = mapping - > host - > i_size ;
if ( pos + len > isize )
vmtruncate ( mapping - > host , isize ) ;
}
return ret ;
2007-10-16 12:25:21 +04:00
}
2005-04-17 02:20:36 +04:00
static sector_t minix_bmap ( struct address_space * mapping , sector_t block )
{
return generic_block_bmap ( mapping , block , minix_get_block ) ;
}
2007-10-16 12:25:21 +04:00
2006-06-28 15:26:44 +04:00
static const struct address_space_operations minix_aops = {
2005-04-17 02:20:36 +04:00
. readpage = minix_readpage ,
. writepage = minix_writepage ,
. sync_page = block_sync_page ,
2007-10-16 12:25:21 +04:00
. write_begin = minix_write_begin ,
. write_end = generic_write_end ,
2005-04-17 02:20:36 +04:00
. bmap = minix_bmap
} ;
2007-02-12 11:55:39 +03:00
static const struct inode_operations minix_symlink_inode_operations = {
2005-04-17 02:20:36 +04:00
. readlink = generic_readlink ,
. follow_link = page_follow_link_light ,
. put_link = page_put_link ,
. getattr = minix_getattr ,
} ;
void minix_set_inode ( struct inode * inode , dev_t rdev )
{
if ( S_ISREG ( inode - > i_mode ) ) {
inode - > i_op = & minix_file_inode_operations ;
inode - > i_fop = & minix_file_operations ;
inode - > i_mapping - > a_ops = & minix_aops ;
} else if ( S_ISDIR ( inode - > i_mode ) ) {
inode - > i_op = & minix_dir_inode_operations ;
inode - > i_fop = & minix_dir_operations ;
inode - > i_mapping - > a_ops = & minix_aops ;
} else if ( S_ISLNK ( inode - > i_mode ) ) {
inode - > i_op = & minix_symlink_inode_operations ;
inode - > i_mapping - > a_ops = & minix_aops ;
} else
init_special_inode ( inode , inode - > i_mode , rdev ) ;
}
/*
* The minix V1 function to read an inode .
*/
2008-02-07 11:15:44 +03:00
static struct inode * V1_minix_iget ( struct inode * inode )
2005-04-17 02:20:36 +04:00
{
struct buffer_head * bh ;
struct minix_inode * raw_inode ;
struct minix_inode_info * minix_inode = minix_i ( inode ) ;
int i ;
raw_inode = minix_V1_raw_inode ( inode - > i_sb , inode - > i_ino , & bh ) ;
if ( ! raw_inode ) {
2008-02-07 11:15:44 +03:00
iget_failed ( inode ) ;
return ERR_PTR ( - EIO ) ;
2005-04-17 02:20:36 +04:00
}
inode - > i_mode = raw_inode - > i_mode ;
inode - > i_uid = ( uid_t ) raw_inode - > i_uid ;
inode - > i_gid = ( gid_t ) raw_inode - > i_gid ;
inode - > i_nlink = raw_inode - > i_nlinks ;
inode - > i_size = raw_inode - > i_size ;
inode - > i_mtime . tv_sec = inode - > i_atime . tv_sec = inode - > i_ctime . tv_sec = raw_inode - > i_time ;
inode - > i_mtime . tv_nsec = 0 ;
inode - > i_atime . tv_nsec = 0 ;
inode - > i_ctime . tv_nsec = 0 ;
2006-09-27 12:50:49 +04:00
inode - > i_blocks = 0 ;
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < 9 ; i + + )
minix_inode - > u . i1_data [ i ] = raw_inode - > i_zone [ i ] ;
minix_set_inode ( inode , old_decode_dev ( raw_inode - > i_zone [ 0 ] ) ) ;
brelse ( bh ) ;
2008-02-07 11:15:44 +03:00
unlock_new_inode ( inode ) ;
return inode ;
2005-04-17 02:20:36 +04:00
}
/*
* The minix V2 function to read an inode .
*/
2008-02-07 11:15:44 +03:00
static struct inode * V2_minix_iget ( struct inode * inode )
2005-04-17 02:20:36 +04:00
{
struct buffer_head * bh ;
struct minix2_inode * raw_inode ;
struct minix_inode_info * minix_inode = minix_i ( inode ) ;
int i ;
raw_inode = minix_V2_raw_inode ( inode - > i_sb , inode - > i_ino , & bh ) ;
if ( ! raw_inode ) {
2008-02-07 11:15:44 +03:00
iget_failed ( inode ) ;
return ERR_PTR ( - EIO ) ;
2005-04-17 02:20:36 +04:00
}
inode - > i_mode = raw_inode - > i_mode ;
inode - > i_uid = ( uid_t ) raw_inode - > i_uid ;
inode - > i_gid = ( gid_t ) raw_inode - > i_gid ;
inode - > i_nlink = raw_inode - > i_nlinks ;
inode - > i_size = raw_inode - > i_size ;
inode - > i_mtime . tv_sec = raw_inode - > i_mtime ;
inode - > i_atime . tv_sec = raw_inode - > i_atime ;
inode - > i_ctime . tv_sec = raw_inode - > i_ctime ;
inode - > i_mtime . tv_nsec = 0 ;
inode - > i_atime . tv_nsec = 0 ;
inode - > i_ctime . tv_nsec = 0 ;
2006-09-27 12:50:49 +04:00
inode - > i_blocks = 0 ;
2005-04-17 02:20:36 +04:00
for ( i = 0 ; i < 10 ; i + + )
minix_inode - > u . i2_data [ i ] = raw_inode - > i_zone [ i ] ;
minix_set_inode ( inode , old_decode_dev ( raw_inode - > i_zone [ 0 ] ) ) ;
brelse ( bh ) ;
2008-02-07 11:15:44 +03:00
unlock_new_inode ( inode ) ;
return inode ;
2005-04-17 02:20:36 +04:00
}
/*
* The global function to read an inode .
*/
2008-02-07 11:15:44 +03:00
struct inode * minix_iget ( struct super_block * sb , unsigned long ino )
2005-04-17 02:20:36 +04:00
{
2008-02-07 11:15:44 +03:00
struct inode * inode ;
inode = iget_locked ( sb , ino ) ;
if ( ! inode )
return ERR_PTR ( - ENOMEM ) ;
if ( ! ( inode - > i_state & I_NEW ) )
return inode ;
2005-04-17 02:20:36 +04:00
if ( INODE_VERSION ( inode ) = = MINIX_V1 )
2008-02-07 11:15:44 +03:00
return V1_minix_iget ( inode ) ;
2005-04-17 02:20:36 +04:00
else
2008-02-07 11:15:44 +03:00
return V2_minix_iget ( inode ) ;
2005-04-17 02:20:36 +04:00
}
/*
* The minix V1 function to synchronize an inode .
*/
static struct buffer_head * V1_minix_update_inode ( struct inode * inode )
{
struct buffer_head * bh ;
struct minix_inode * raw_inode ;
struct minix_inode_info * minix_inode = minix_i ( inode ) ;
int i ;
raw_inode = minix_V1_raw_inode ( inode - > i_sb , inode - > i_ino , & bh ) ;
if ( ! raw_inode )
return NULL ;
raw_inode - > i_mode = inode - > i_mode ;
raw_inode - > i_uid = fs_high2lowuid ( inode - > i_uid ) ;
raw_inode - > i_gid = fs_high2lowgid ( inode - > i_gid ) ;
raw_inode - > i_nlinks = inode - > i_nlink ;
raw_inode - > i_size = inode - > i_size ;
raw_inode - > i_time = inode - > i_mtime . tv_sec ;
if ( S_ISCHR ( inode - > i_mode ) | | S_ISBLK ( inode - > i_mode ) )
raw_inode - > i_zone [ 0 ] = old_encode_dev ( inode - > i_rdev ) ;
else for ( i = 0 ; i < 9 ; i + + )
raw_inode - > i_zone [ i ] = minix_inode - > u . i1_data [ i ] ;
mark_buffer_dirty ( bh ) ;
return bh ;
}
/*
* The minix V2 function to synchronize an inode .
*/
static struct buffer_head * V2_minix_update_inode ( struct inode * inode )
{
struct buffer_head * bh ;
struct minix2_inode * raw_inode ;
struct minix_inode_info * minix_inode = minix_i ( inode ) ;
int i ;
raw_inode = minix_V2_raw_inode ( inode - > i_sb , inode - > i_ino , & bh ) ;
if ( ! raw_inode )
return NULL ;
raw_inode - > i_mode = inode - > i_mode ;
raw_inode - > i_uid = fs_high2lowuid ( inode - > i_uid ) ;
raw_inode - > i_gid = fs_high2lowgid ( inode - > i_gid ) ;
raw_inode - > i_nlinks = inode - > i_nlink ;
raw_inode - > i_size = inode - > i_size ;
raw_inode - > i_mtime = inode - > i_mtime . tv_sec ;
raw_inode - > i_atime = inode - > i_atime . tv_sec ;
raw_inode - > i_ctime = inode - > i_ctime . tv_sec ;
if ( S_ISCHR ( inode - > i_mode ) | | S_ISBLK ( inode - > i_mode ) )
raw_inode - > i_zone [ 0 ] = old_encode_dev ( inode - > i_rdev ) ;
else for ( i = 0 ; i < 10 ; i + + )
raw_inode - > i_zone [ i ] = minix_inode - > u . i2_data [ i ] ;
mark_buffer_dirty ( bh ) ;
return bh ;
}
2010-03-05 11:21:37 +03:00
static int minix_write_inode ( struct inode * inode , struct writeback_control * wbc )
2005-04-17 02:20:36 +04:00
{
int err = 0 ;
struct buffer_head * bh ;
2009-06-07 23:21:06 +04:00
if ( INODE_VERSION ( inode ) = = MINIX_V1 )
bh = V1_minix_update_inode ( inode ) ;
else
bh = V2_minix_update_inode ( inode ) ;
if ( ! bh )
return - EIO ;
2010-03-05 11:21:37 +03:00
if ( wbc - > sync_mode = = WB_SYNC_ALL & & buffer_dirty ( bh ) ) {
2005-04-17 02:20:36 +04:00
sync_dirty_buffer ( bh ) ;
2009-06-07 23:21:06 +04:00
if ( buffer_req ( bh ) & & ! buffer_uptodate ( bh ) ) {
2006-03-25 14:07:42 +03:00
printk ( " IO error syncing minix inode [%s:%08lx] \n " ,
2005-04-17 02:20:36 +04:00
inode - > i_sb - > s_id , inode - > i_ino ) ;
2009-06-07 23:21:06 +04:00
err = - EIO ;
2005-04-17 02:20:36 +04:00
}
}
brelse ( bh ) ;
return err ;
}
int minix_getattr ( struct vfsmount * mnt , struct dentry * dentry , struct kstat * stat )
{
2007-02-12 11:52:49 +03:00
struct inode * dir = dentry - > d_parent - > d_inode ;
struct super_block * sb = dir - > i_sb ;
2005-04-17 02:20:36 +04:00
generic_fillattr ( dentry - > d_inode , stat ) ;
if ( INODE_VERSION ( dentry - > d_inode ) = = MINIX_V1 )
2007-02-12 11:52:49 +03:00
stat - > blocks = ( BLOCK_SIZE / 512 ) * V1_minix_blocks ( stat - > size , sb ) ;
2005-04-17 02:20:36 +04:00
else
2007-02-12 11:52:49 +03:00
stat - > blocks = ( sb - > s_blocksize / 512 ) * V2_minix_blocks ( stat - > size , sb ) ;
stat - > blksize = sb - > s_blocksize ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
/*
* The function that is called for file truncation .
*/
void minix_truncate ( struct inode * inode )
{
if ( ! ( S_ISREG ( inode - > i_mode ) | | S_ISDIR ( inode - > i_mode ) | | S_ISLNK ( inode - > i_mode ) ) )
return ;
if ( INODE_VERSION ( inode ) = = MINIX_V1 )
V1_minix_truncate ( inode ) ;
else
V2_minix_truncate ( inode ) ;
}
2010-07-25 00:46:55 +04:00
static struct dentry * minix_mount ( struct file_system_type * fs_type ,
int flags , const char * dev_name , void * data )
2005-04-17 02:20:36 +04:00
{
2010-07-25 00:46:55 +04:00
return mount_bdev ( fs_type , flags , dev_name , data , minix_fill_super ) ;
2005-04-17 02:20:36 +04:00
}
static struct file_system_type minix_fs_type = {
. owner = THIS_MODULE ,
. name = " minix " ,
2010-07-25 00:46:55 +04:00
. mount = minix_mount ,
2005-04-17 02:20:36 +04:00
. kill_sb = kill_block_super ,
. fs_flags = FS_REQUIRES_DEV ,
} ;
static int __init init_minix_fs ( void )
{
int err = init_inodecache ( ) ;
if ( err )
goto out1 ;
err = register_filesystem ( & minix_fs_type ) ;
if ( err )
goto out ;
return 0 ;
out :
destroy_inodecache ( ) ;
out1 :
return err ;
}
static void __exit exit_minix_fs ( void )
{
unregister_filesystem ( & minix_fs_type ) ;
destroy_inodecache ( ) ;
}
module_init ( init_minix_fs )
module_exit ( exit_minix_fs )
MODULE_LICENSE ( " GPL " ) ;