2005-04-17 02:20:36 +04:00
/*
* fs / bfs / inode . c
* BFS superblock and inode operations .
2006-12-13 11:35:14 +03:00
* Copyright ( C ) 1999 - 2006 Tigran Aivazian < tigran @ aivazian . fsnet . co . uk >
2005-04-17 02:20:36 +04:00
* From fs / minix , Copyright ( C ) 1991 , 1992 Linus Torvalds .
2005-09-10 00:02:04 +04:00
*
* Made endianness - clean by Andrew Stribblehill < ads @ wompom . org > , 2005.
2005-04-17 02:20:36 +04:00
*/
# include <linux/module.h>
# include <linux/mm.h>
# include <linux/slab.h>
# include <linux/init.h>
# include <linux/fs.h>
# include <linux/buffer_head.h>
# include <linux/vfs.h>
2010-03-05 11:21:37 +03:00
# include <linux/writeback.h>
2015-02-22 19:58:50 +03:00
# include <linux/uio.h>
2016-12-24 22:46:01 +03:00
# include <linux/uaccess.h>
2005-04-17 02:20:36 +04:00
# include "bfs.h"
2006-12-13 11:35:14 +03:00
MODULE_AUTHOR ( " Tigran Aivazian <tigran@aivazian.fsnet.co.uk> " ) ;
2005-04-17 02:20:36 +04:00
MODULE_DESCRIPTION ( " SCO UnixWare BFS filesystem for Linux " ) ;
MODULE_LICENSE ( " GPL " ) ;
# undef DEBUG
# ifdef DEBUG
# define dprintf(x...) printf(x)
# else
# define dprintf(x...)
# endif
2008-02-07 11:15:32 +03:00
struct inode * bfs_iget ( struct super_block * sb , unsigned long ino )
2005-04-17 02:20:36 +04:00
{
2007-11-15 03:59:47 +03:00
struct bfs_inode * di ;
2008-02-07 11:15:32 +03:00
struct inode * inode ;
2007-11-15 03:59:47 +03:00
struct buffer_head * bh ;
2005-04-17 02:20:36 +04:00
int block , off ;
2008-02-07 11:15:32 +03:00
inode = iget_locked ( sb , ino ) ;
2013-08-14 13:51:03 +04:00
if ( ! inode )
2008-02-07 11:15:32 +03:00
return ERR_PTR ( - ENOMEM ) ;
if ( ! ( inode - > i_state & I_NEW ) )
return inode ;
2007-11-15 03:59:47 +03:00
if ( ( ino < BFS_ROOT_INO ) | | ( ino > BFS_SB ( inode - > i_sb ) - > si_lasti ) ) {
2005-04-17 02:20:36 +04:00
printf ( " Bad inode number %s:%08lx \n " , inode - > i_sb - > s_id , ino ) ;
2008-02-07 11:15:32 +03:00
goto error ;
2005-04-17 02:20:36 +04:00
}
2007-11-15 03:59:47 +03:00
block = ( ino - BFS_ROOT_INO ) / BFS_INODES_PER_BLOCK + 1 ;
2005-04-17 02:20:36 +04:00
bh = sb_bread ( inode - > i_sb , block ) ;
if ( ! bh ) {
2007-11-15 03:59:47 +03:00
printf ( " Unable to read inode %s:%08lx \n " , inode - > i_sb - > s_id ,
ino ) ;
2008-02-07 11:15:32 +03:00
goto error ;
2005-04-17 02:20:36 +04:00
}
off = ( ino - BFS_ROOT_INO ) % BFS_INODES_PER_BLOCK ;
di = ( struct bfs_inode * ) bh - > b_data + off ;
2007-11-15 03:59:47 +03:00
inode - > i_mode = 0x0000FFFF & le32_to_cpu ( di - > i_mode ) ;
2005-09-10 00:02:04 +04:00
if ( le32_to_cpu ( di - > i_vtype ) = = BFS_VDIR ) {
2005-04-17 02:20:36 +04:00
inode - > i_mode | = S_IFDIR ;
inode - > i_op = & bfs_dir_inops ;
inode - > i_fop = & bfs_dir_operations ;
2005-09-10 00:02:04 +04:00
} else if ( le32_to_cpu ( di - > i_vtype ) = = BFS_VREG ) {
2005-04-17 02:20:36 +04:00
inode - > i_mode | = S_IFREG ;
inode - > i_op = & bfs_file_inops ;
inode - > i_fop = & bfs_file_operations ;
inode - > i_mapping - > a_ops = & bfs_aops ;
}
2005-09-10 00:02:04 +04:00
BFS_I ( inode ) - > i_sblock = le32_to_cpu ( di - > i_sblock ) ;
BFS_I ( inode ) - > i_eblock = le32_to_cpu ( di - > i_eblock ) ;
2007-11-15 03:59:47 +03:00
BFS_I ( inode ) - > i_dsk_ino = le16_to_cpu ( di - > i_ino ) ;
2012-04-25 14:57:31 +04:00
i_uid_write ( inode , le32_to_cpu ( di - > i_uid ) ) ;
i_gid_write ( inode , le32_to_cpu ( di - > i_gid ) ) ;
2011-10-28 16:13:29 +04:00
set_nlink ( inode , le32_to_cpu ( di - > i_nlink ) ) ;
2005-04-17 02:20:36 +04:00
inode - > i_size = BFS_FILESIZE ( di ) ;
inode - > i_blocks = BFS_FILEBLOCKS ( di ) ;
2005-09-10 00:02:04 +04:00
inode - > i_atime . tv_sec = le32_to_cpu ( di - > i_atime ) ;
inode - > i_mtime . tv_sec = le32_to_cpu ( di - > i_mtime ) ;
inode - > i_ctime . tv_sec = le32_to_cpu ( di - > i_ctime ) ;
2005-04-17 02:20:36 +04:00
inode - > i_atime . tv_nsec = 0 ;
inode - > i_mtime . tv_nsec = 0 ;
inode - > i_ctime . tv_nsec = 0 ;
brelse ( bh ) ;
2008-02-07 11:15:32 +03:00
unlock_new_inode ( inode ) ;
return inode ;
error :
iget_failed ( inode ) ;
return ERR_PTR ( - EIO ) ;
2005-04-17 02:20:36 +04:00
}
2010-06-06 17:50:39 +04:00
static struct bfs_inode * find_inode ( struct super_block * sb , u16 ino , struct buffer_head * * p )
{
if ( ( ino < BFS_ROOT_INO ) | | ( ino > BFS_SB ( sb ) - > si_lasti ) ) {
printf ( " Bad inode number %s:%08x \n " , sb - > s_id , ino ) ;
return ERR_PTR ( - EIO ) ;
}
ino - = BFS_ROOT_INO ;
* p = sb_bread ( sb , 1 + ino / BFS_INODES_PER_BLOCK ) ;
if ( ! * p ) {
printf ( " Unable to read inode %s:%08x \n " , sb - > s_id , ino ) ;
return ERR_PTR ( - EIO ) ;
}
return ( struct bfs_inode * ) ( * p ) - > b_data + ino % BFS_INODES_PER_BLOCK ;
}
2010-03-05 11:21:37 +03:00
static int bfs_write_inode ( struct inode * inode , struct writeback_control * wbc )
2005-04-17 02:20:36 +04:00
{
2009-06-08 09:15:58 +04:00
struct bfs_sb_info * info = BFS_SB ( inode - > i_sb ) ;
2005-09-10 00:02:04 +04:00
unsigned int ino = ( u16 ) inode - > i_ino ;
unsigned long i_sblock ;
2007-11-15 03:59:47 +03:00
struct bfs_inode * di ;
struct buffer_head * bh ;
2009-06-08 09:15:58 +04:00
int err = 0 ;
2005-04-17 02:20:36 +04:00
2005-09-10 00:02:04 +04:00
dprintf ( " ino=%08x \n " , ino ) ;
2010-06-06 17:50:39 +04:00
di = find_inode ( inode - > i_sb , ino , & bh ) ;
if ( IS_ERR ( di ) )
return PTR_ERR ( di ) ;
2005-04-17 02:20:36 +04:00
2008-07-26 06:44:54 +04:00
mutex_lock ( & info - > bfs_lock ) ;
2005-04-17 02:20:36 +04:00
2005-09-10 00:02:04 +04:00
if ( ino = = BFS_ROOT_INO )
di - > i_vtype = cpu_to_le32 ( BFS_VDIR ) ;
2005-04-17 02:20:36 +04:00
else
2005-09-10 00:02:04 +04:00
di - > i_vtype = cpu_to_le32 ( BFS_VREG ) ;
di - > i_ino = cpu_to_le16 ( ino ) ;
di - > i_mode = cpu_to_le32 ( inode - > i_mode ) ;
2012-04-25 14:57:31 +04:00
di - > i_uid = cpu_to_le32 ( i_uid_read ( inode ) ) ;
di - > i_gid = cpu_to_le32 ( i_gid_read ( inode ) ) ;
2005-09-10 00:02:04 +04:00
di - > i_nlink = cpu_to_le32 ( inode - > i_nlink ) ;
di - > i_atime = cpu_to_le32 ( inode - > i_atime . tv_sec ) ;
di - > i_mtime = cpu_to_le32 ( inode - > i_mtime . tv_sec ) ;
di - > i_ctime = cpu_to_le32 ( inode - > i_ctime . tv_sec ) ;
i_sblock = BFS_I ( inode ) - > i_sblock ;
di - > i_sblock = cpu_to_le32 ( i_sblock ) ;
di - > i_eblock = cpu_to_le32 ( BFS_I ( inode ) - > i_eblock ) ;
di - > i_eoffset = cpu_to_le32 ( i_sblock * BFS_BSIZE + inode - > i_size - 1 ) ;
2005-04-17 02:20:36 +04:00
mark_buffer_dirty ( bh ) ;
2010-03-05 11:21:37 +03:00
if ( wbc - > sync_mode = = WB_SYNC_ALL ) {
2009-06-08 09:15:58 +04:00
sync_dirty_buffer ( bh ) ;
if ( buffer_req ( bh ) & & ! buffer_uptodate ( bh ) )
err = - EIO ;
}
2005-04-17 02:20:36 +04:00
brelse ( bh ) ;
2008-07-26 06:44:54 +04:00
mutex_unlock ( & info - > bfs_lock ) ;
2009-06-08 09:15:58 +04:00
return err ;
2005-04-17 02:20:36 +04:00
}
2010-06-06 17:50:39 +04:00
static void bfs_evict_inode ( struct inode * inode )
2005-04-17 02:20:36 +04:00
{
unsigned long ino = inode - > i_ino ;
2007-11-15 03:59:47 +03:00
struct bfs_inode * di ;
struct buffer_head * bh ;
struct super_block * s = inode - > i_sb ;
struct bfs_sb_info * info = BFS_SB ( s ) ;
struct bfs_inode_info * bi = BFS_I ( inode ) ;
2005-04-17 02:20:36 +04:00
2005-09-10 00:02:04 +04:00
dprintf ( " ino=%08lx \n " , ino ) ;
2005-04-17 02:20:36 +04:00
2014-04-04 01:47:49 +04:00
truncate_inode_pages_final ( & inode - > i_data ) ;
2010-06-06 17:50:39 +04:00
invalidate_inode_buffers ( inode ) ;
2012-05-03 16:48:02 +04:00
clear_inode ( inode ) ;
2005-09-10 00:01:31 +04:00
2010-06-06 17:50:39 +04:00
if ( inode - > i_nlink )
2005-04-17 02:20:36 +04:00
return ;
2007-11-15 03:59:47 +03:00
2010-06-06 17:50:39 +04:00
di = find_inode ( s , inode - > i_ino , & bh ) ;
if ( IS_ERR ( di ) )
2005-04-17 02:20:36 +04:00
return ;
2010-06-06 17:50:39 +04:00
mutex_lock ( & info - > bfs_lock ) ;
/* clear on-disk inode */
memset ( di , 0 , sizeof ( struct bfs_inode ) ) ;
2007-11-15 03:59:47 +03:00
mark_buffer_dirty ( bh ) ;
brelse ( bh ) ;
2005-09-10 00:02:04 +04:00
if ( bi - > i_dsk_ino ) {
2007-12-05 11:32:52 +03:00
if ( bi - > i_sblock )
info - > si_freeb + = bi - > i_eblock + 1 - bi - > i_sblock ;
2005-04-17 02:20:36 +04:00
info - > si_freei + + ;
2005-09-10 00:02:04 +04:00
clear_bit ( ino , info - > si_imap ) ;
2014-08-09 01:22:29 +04:00
bfs_dump_imap ( " delete_inode " , s ) ;
2005-09-10 00:02:04 +04:00
}
2005-04-17 02:20:36 +04:00
2007-11-15 03:59:47 +03:00
/*
* If this was the last file , make the previous block
* " last block of the last file " even if there is no
* real file there , saves us 1 gap .
*/
2010-07-05 16:15:01 +04:00
if ( info - > si_lf_eblk = = bi - > i_eblock )
2007-11-15 03:59:47 +03:00
info - > si_lf_eblk = bi - > i_sblock - 1 ;
2008-07-26 06:44:54 +04:00
mutex_unlock ( & info - > bfs_lock ) ;
2005-04-17 02:20:36 +04:00
}
static void bfs_put_super ( struct super_block * s )
{
struct bfs_sb_info * info = BFS_SB ( s ) ;
2008-07-26 06:44:54 +04:00
2009-01-07 01:43:12 +03:00
if ( ! info )
return ;
2008-07-26 06:44:54 +04:00
mutex_destroy ( & info - > bfs_lock ) ;
2005-04-17 02:20:36 +04:00
kfree ( info - > si_imap ) ;
kfree ( info ) ;
s - > s_fs_info = NULL ;
}
2006-06-23 13:02:58 +04:00
static int bfs_statfs ( struct dentry * dentry , struct kstatfs * buf )
2005-04-17 02:20:36 +04:00
{
2006-06-23 13:02:58 +04:00
struct super_block * s = dentry - > d_sb ;
2005-04-17 02:20:36 +04:00
struct bfs_sb_info * info = BFS_SB ( s ) ;
u64 id = huge_encode_dev ( s - > s_bdev - > bd_dev ) ;
buf - > f_type = BFS_MAGIC ;
buf - > f_bsize = s - > s_blocksize ;
buf - > f_blocks = info - > si_blocks ;
buf - > f_bfree = buf - > f_bavail = info - > si_freeb ;
buf - > f_files = info - > si_lasti + 1 - BFS_ROOT_INO ;
buf - > f_ffree = info - > si_freei ;
buf - > f_fsid . val [ 0 ] = ( u32 ) id ;
buf - > f_fsid . val [ 1 ] = ( u32 ) ( id > > 32 ) ;
buf - > f_namelen = BFS_NAMELEN ;
return 0 ;
}
2007-11-15 03:59:47 +03:00
static struct kmem_cache * bfs_inode_cachep ;
2005-04-17 02:20:36 +04:00
static struct inode * bfs_alloc_inode ( struct super_block * sb )
{
struct bfs_inode_info * bi ;
2006-12-07 07:33:17 +03:00
bi = kmem_cache_alloc ( bfs_inode_cachep , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! bi )
return NULL ;
return & bi - > vfs_inode ;
}
2011-01-07 09:49:49 +03:00
static void bfs_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 ) ;
2005-04-17 02:20:36 +04:00
kmem_cache_free ( bfs_inode_cachep , BFS_I ( inode ) ) ;
}
2011-01-07 09:49:49 +03:00
static void bfs_destroy_inode ( struct inode * inode )
{
call_rcu ( & inode - > i_rcu , bfs_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 bfs_inode_info * bi = foo ;
2007-05-17 09:10:57 +04:00
inode_init_once ( & bi - > vfs_inode ) ;
2005-04-17 02:20:36 +04:00
}
2007-07-20 05:11:58 +04:00
2014-04-08 02:39:02 +04:00
static int __init init_inodecache ( void )
2005-04-17 02:20:36 +04:00
{
bfs_inode_cachep = kmem_cache_create ( " bfs_inode_cache " ,
sizeof ( struct bfs_inode_info ) ,
2006-03-24 14:16:06 +03:00
0 , ( SLAB_RECLAIM_ACCOUNT |
2016-01-15 02:18:21 +03:00
SLAB_MEM_SPREAD | SLAB_ACCOUNT ) ,
2007-07-20 05:11:58 +04:00
init_once ) ;
2005-04-17 02:20:36 +04:00
if ( bfs_inode_cachep = = NULL )
return - ENOMEM ;
return 0 ;
}
static void destroy_inodecache ( void )
{
2012-09-26 05:33:07 +04:00
/*
* Make sure all delayed rcu free inodes are flushed before we
* destroy cache .
*/
rcu_barrier ( ) ;
2006-09-27 12:49:40 +04:00
kmem_cache_destroy ( bfs_inode_cachep ) ;
2005-04-17 02:20:36 +04:00
}
2007-02-12 11:55:41 +03:00
static const struct super_operations bfs_sops = {
2005-04-17 02:20:36 +04:00
. alloc_inode = bfs_alloc_inode ,
. destroy_inode = bfs_destroy_inode ,
. write_inode = bfs_write_inode ,
2010-06-06 17:50:39 +04:00
. evict_inode = bfs_evict_inode ,
2005-04-17 02:20:36 +04:00
. put_super = bfs_put_super ,
. statfs = bfs_statfs ,
} ;
2014-08-09 01:22:29 +04:00
void bfs_dump_imap ( const char * prefix , struct super_block * s )
2005-04-17 02:20:36 +04:00
{
2005-09-10 00:02:04 +04:00
# ifdef DEBUG
2005-04-17 02:20:36 +04:00
int i ;
char * tmpbuf = ( char * ) get_zeroed_page ( GFP_KERNEL ) ;
if ( ! tmpbuf )
return ;
2007-11-15 03:59:47 +03:00
for ( i = BFS_SB ( s ) - > si_lasti ; i > = 0 ; i - - ) {
if ( i > PAGE_SIZE - 100 ) break ;
2005-04-17 02:20:36 +04:00
if ( test_bit ( i , BFS_SB ( s ) - > si_imap ) )
strcat ( tmpbuf , " 1 " ) ;
else
strcat ( tmpbuf , " 0 " ) ;
}
2007-11-15 03:59:47 +03:00
printf ( " BFS-fs: %s: lasti=%08lx <%s> \n " ,
prefix , BFS_SB ( s ) - > si_lasti , tmpbuf ) ;
2005-04-17 02:20:36 +04:00
free_page ( ( unsigned long ) tmpbuf ) ;
# endif
}
static int bfs_fill_super ( struct super_block * s , void * data , int silent )
{
2010-07-05 16:15:01 +04:00
struct buffer_head * bh , * sbh ;
2007-11-15 03:59:47 +03:00
struct bfs_super_block * bfs_sb ;
struct inode * inode ;
2005-09-10 00:02:04 +04:00
unsigned i , imap_len ;
2007-11-15 03:59:47 +03:00
struct bfs_sb_info * info ;
2010-01-24 08:52:22 +03:00
int ret = - EINVAL ;
2009-01-07 01:43:12 +03:00
unsigned long i_sblock , i_eblock , i_eoff , s_size ;
2005-04-17 02:20:36 +04:00
2006-09-27 12:49:37 +04:00
info = kzalloc ( sizeof ( * info ) , GFP_KERNEL ) ;
2010-02-24 15:25:29 +03:00
if ( ! info )
2005-04-17 02:20:36 +04:00
return - ENOMEM ;
2010-01-24 08:52:22 +03:00
mutex_init ( & info - > bfs_lock ) ;
2005-04-17 02:20:36 +04:00
s - > s_fs_info = info ;
sb_set_blocksize ( s , BFS_BSIZE ) ;
2010-07-05 16:15:01 +04:00
sbh = sb_bread ( s , 0 ) ;
if ( ! sbh )
2005-04-17 02:20:36 +04:00
goto out ;
2010-07-05 16:15:01 +04:00
bfs_sb = ( struct bfs_super_block * ) sbh - > b_data ;
2005-09-10 00:02:04 +04:00
if ( le32_to_cpu ( bfs_sb - > s_magic ) ! = BFS_MAGIC ) {
2005-04-17 02:20:36 +04:00
if ( ! silent )
printf ( " No BFS filesystem on %s (magic=%08x) \n " ,
2005-09-10 00:02:04 +04:00
s - > s_id , le32_to_cpu ( bfs_sb - > s_magic ) ) ;
2010-01-24 08:52:22 +03:00
goto out1 ;
2005-04-17 02:20:36 +04:00
}
if ( BFS_UNCLEAN ( bfs_sb , s ) & & ! silent )
printf ( " %s is unclean, continuing \n " , s - > s_id ) ;
s - > s_magic = BFS_MAGIC ;
2009-01-07 01:43:12 +03:00
if ( le32_to_cpu ( bfs_sb - > s_start ) > le32_to_cpu ( bfs_sb - > s_end ) ) {
printf ( " Superblock is corrupted \n " ) ;
2010-01-24 08:52:22 +03:00
goto out1 ;
2009-01-07 01:43:12 +03:00
}
2007-11-15 03:59:47 +03:00
info - > si_lasti = ( le32_to_cpu ( bfs_sb - > s_start ) - BFS_BSIZE ) /
sizeof ( struct bfs_inode )
+ BFS_ROOT_INO - 1 ;
imap_len = ( info - > si_lasti / 8 ) + 1 ;
2006-09-27 12:49:37 +04:00
info - > si_imap = kzalloc ( imap_len , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! info - > si_imap )
2010-01-24 08:52:22 +03:00
goto out1 ;
2007-11-15 03:59:47 +03:00
for ( i = 0 ; i < BFS_ROOT_INO ; i + + )
2005-04-17 02:20:36 +04:00
set_bit ( i , info - > si_imap ) ;
s - > s_op = & bfs_sops ;
2008-02-07 11:15:32 +03:00
inode = bfs_iget ( s , BFS_ROOT_INO ) ;
if ( IS_ERR ( inode ) ) {
ret = PTR_ERR ( inode ) ;
2010-01-24 08:52:22 +03:00
goto out2 ;
2005-04-17 02:20:36 +04:00
}
2012-01-09 07:15:13 +04:00
s - > s_root = d_make_root ( inode ) ;
2005-04-17 02:20:36 +04:00
if ( ! s - > s_root ) {
2008-02-07 11:15:32 +03:00
ret = - ENOMEM ;
2010-01-24 08:52:22 +03:00
goto out2 ;
2005-04-17 02:20:36 +04:00
}
2007-11-15 03:59:47 +03:00
info - > si_blocks = ( le32_to_cpu ( bfs_sb - > s_end ) + 1 ) > > BFS_BSIZE_BITS ;
info - > si_freeb = ( le32_to_cpu ( bfs_sb - > s_end ) + 1
- le32_to_cpu ( bfs_sb - > s_start ) ) > > BFS_BSIZE_BITS ;
2005-04-17 02:20:36 +04:00
info - > si_freei = 0 ;
info - > si_lf_eblk = 0 ;
2009-01-07 01:43:13 +03:00
/* can we read the last block? */
bh = sb_bread ( s , info - > si_blocks - 1 ) ;
if ( ! bh ) {
printf ( " Last block not available: %lu \n " , info - > si_blocks - 1 ) ;
ret = - EIO ;
2010-01-24 08:52:22 +03:00
goto out3 ;
2009-01-07 01:43:13 +03:00
}
brelse ( bh ) ;
2005-10-04 20:48:44 +04:00
bh = NULL ;
2007-11-15 03:59:47 +03:00
for ( i = BFS_ROOT_INO ; i < = info - > si_lasti ; i + + ) {
2005-10-04 20:48:44 +04:00
struct bfs_inode * di ;
2007-11-15 03:59:47 +03:00
int block = ( i - BFS_ROOT_INO ) / BFS_INODES_PER_BLOCK + 1 ;
2005-10-04 20:48:44 +04:00
int off = ( i - BFS_ROOT_INO ) % BFS_INODES_PER_BLOCK ;
2008-07-26 06:44:52 +04:00
unsigned long eblock ;
2005-10-04 20:48:44 +04:00
if ( ! off ) {
brelse ( bh ) ;
bh = sb_bread ( s , block ) ;
}
if ( ! bh )
continue ;
di = ( struct bfs_inode * ) bh - > b_data + off ;
2009-01-07 01:43:12 +03:00
/* test if filesystem is not corrupted */
i_eoff = le32_to_cpu ( di - > i_eoffset ) ;
i_sblock = le32_to_cpu ( di - > i_sblock ) ;
i_eblock = le32_to_cpu ( di - > i_eblock ) ;
s_size = le32_to_cpu ( bfs_sb - > s_end ) ;
if ( i_sblock > info - > si_blocks | |
i_eblock > info - > si_blocks | |
i_sblock > i_eblock | |
i_eoff > s_size | |
i_sblock * BFS_BSIZE > i_eoff ) {
printf ( " Inode 0x%08x corrupted \n " , i ) ;
brelse ( bh ) ;
2010-01-24 08:52:22 +03:00
ret = - EIO ;
goto out3 ;
2009-01-07 01:43:12 +03:00
}
2005-10-04 20:48:44 +04:00
if ( ! di - > i_ino ) {
2005-04-17 02:20:36 +04:00
info - > si_freei + + ;
2005-10-04 20:48:44 +04:00
continue ;
}
set_bit ( i , info - > si_imap ) ;
info - > si_freeb - = BFS_FILEBLOCKS ( di ) ;
eblock = le32_to_cpu ( di - > i_eblock ) ;
2007-11-15 03:59:47 +03:00
if ( eblock > info - > si_lf_eblk )
2005-10-04 20:48:44 +04:00
info - > si_lf_eblk = eblock ;
2005-04-17 02:20:36 +04:00
}
2005-10-04 20:48:44 +04:00
brelse ( bh ) ;
2010-07-05 16:15:01 +04:00
brelse ( sbh ) ;
2014-08-09 01:22:29 +04:00
bfs_dump_imap ( " read_super " , s ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2010-01-24 08:52:22 +03:00
out3 :
dput ( s - > s_root ) ;
s - > s_root = NULL ;
out2 :
kfree ( info - > si_imap ) ;
out1 :
2010-07-05 16:15:01 +04:00
brelse ( sbh ) ;
2005-04-17 02:20:36 +04:00
out :
2010-01-24 08:52:22 +03:00
mutex_destroy ( & info - > bfs_lock ) ;
2005-04-17 02:20:36 +04:00
kfree ( info ) ;
s - > s_fs_info = NULL ;
2008-02-07 11:15:32 +03:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2010-07-25 00:46:55 +04:00
static struct dentry * bfs_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 , bfs_fill_super ) ;
2005-04-17 02:20:36 +04:00
}
static struct file_system_type bfs_fs_type = {
. owner = THIS_MODULE ,
. name = " bfs " ,
2010-07-25 00:46:55 +04:00
. mount = bfs_mount ,
2005-04-17 02:20:36 +04:00
. kill_sb = kill_block_super ,
. fs_flags = FS_REQUIRES_DEV ,
} ;
2013-03-03 07:39:14 +04:00
MODULE_ALIAS_FS ( " bfs " ) ;
2005-04-17 02:20:36 +04:00
static int __init init_bfs_fs ( void )
{
int err = init_inodecache ( ) ;
if ( err )
goto out1 ;
err = register_filesystem ( & bfs_fs_type ) ;
if ( err )
goto out ;
return 0 ;
out :
destroy_inodecache ( ) ;
out1 :
return err ;
}
static void __exit exit_bfs_fs ( void )
{
unregister_filesystem ( & bfs_fs_type ) ;
destroy_inodecache ( ) ;
}
module_init ( init_bfs_fs )
module_exit ( exit_bfs_fs )