2005-04-17 02:20:36 +04:00
/*
* Copyright ( c ) 2000 - 2001 Christoph Hellwig .
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions , and the following disclaimer ,
* without modification .
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* Alternatively , this software may be distributed under the terms of the
* GNU General Public License ( " GPL " ) .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ` ` AS IS ' ' AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
*/
/*
* Veritas filesystem driver - superblock related routines .
*/
# include <linux/init.h>
# include <linux/module.h>
# include <linux/blkdev.h>
# include <linux/fs.h>
# include <linux/buffer_head.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/stat.h>
# include <linux/vfs.h>
2006-06-23 13:02:58 +04:00
# include <linux/mount.h>
2005-04-17 02:20:36 +04:00
# include "vxfs.h"
# include "vxfs_extern.h"
# include "vxfs_dir.h"
# include "vxfs_inode.h"
MODULE_AUTHOR ( " Christoph Hellwig " ) ;
MODULE_DESCRIPTION ( " Veritas Filesystem (VxFS) driver " ) ;
MODULE_LICENSE ( " Dual BSD/GPL " ) ;
static void vxfs_put_super ( struct super_block * ) ;
2006-06-23 13:02:58 +04:00
static int vxfs_statfs ( struct dentry * , struct kstatfs * ) ;
2005-04-17 02:20:36 +04:00
static int vxfs_remount ( struct super_block * , int * , char * ) ;
2007-02-12 11:55:41 +03:00
static const struct super_operations vxfs_super_ops = {
2010-06-07 22:34:48 +04:00
. evict_inode = vxfs_evict_inode ,
2005-04-17 02:20:36 +04:00
. put_super = vxfs_put_super ,
. statfs = vxfs_statfs ,
. remount_fs = vxfs_remount ,
} ;
/**
* vxfs_put_super - free superblock resources
* @ sbp : VFS superblock .
*
* Description :
* vxfs_put_super frees all resources allocated for @ sbp
* after the last instance of the filesystem is unmounted .
*/
static void
vxfs_put_super ( struct super_block * sbp )
{
struct vxfs_sb_info * infp = VXFS_SBI ( sbp ) ;
vxfs_put_fake_inode ( infp - > vsi_fship ) ;
vxfs_put_fake_inode ( infp - > vsi_ilist ) ;
vxfs_put_fake_inode ( infp - > vsi_stilist ) ;
brelse ( infp - > vsi_bp ) ;
kfree ( infp ) ;
}
/**
* vxfs_statfs - get filesystem information
2006-06-23 13:02:58 +04:00
* @ dentry : VFS dentry to locate superblock
2005-04-17 02:20:36 +04:00
* @ bufp : output buffer
*
* Description :
* vxfs_statfs fills the statfs buffer @ bufp with information
2006-06-23 13:02:58 +04:00
* about the filesystem described by @ dentry .
2005-04-17 02:20:36 +04:00
*
* Returns :
* Zero .
*
* Locking :
* No locks held .
*
* Notes :
* This is everything but complete . . .
*/
static int
2006-06-23 13:02:58 +04:00
vxfs_statfs ( struct dentry * dentry , struct kstatfs * bufp )
2005-04-17 02:20:36 +04:00
{
2006-06-23 13:02:58 +04:00
struct vxfs_sb_info * infp = VXFS_SBI ( dentry - > d_sb ) ;
2005-04-17 02:20:36 +04:00
bufp - > f_type = VXFS_SUPER_MAGIC ;
2006-06-23 13:02:58 +04:00
bufp - > f_bsize = dentry - > d_sb - > s_blocksize ;
2005-04-17 02:20:36 +04:00
bufp - > f_blocks = infp - > vsi_raw - > vs_dsize ;
bufp - > f_bfree = infp - > vsi_raw - > vs_free ;
bufp - > f_bavail = 0 ;
bufp - > f_files = 0 ;
bufp - > f_ffree = infp - > vsi_raw - > vs_ifree ;
bufp - > f_namelen = VXFS_NAMELEN ;
return 0 ;
}
static int vxfs_remount ( struct super_block * sb , int * flags , char * data )
{
2014-03-13 18:14:33 +04:00
sync_filesystem ( sb ) ;
2005-04-17 02:20:36 +04:00
* flags | = MS_RDONLY ;
return 0 ;
}
/**
2010-06-11 14:17:00 +04:00
* vxfs_read_super - read superblock into memory and initialize filesystem
2005-04-17 02:20:36 +04:00
* @ sbp : VFS superblock ( to fill )
* @ dp : fs private mount data
* @ silent : do not complain loudly when sth is wrong
*
* Description :
* We are called on the first mount of a filesystem to read the
* superblock into memory and do some basic setup .
*
* Returns :
* The superblock on success , else % NULL .
*
* Locking :
2010-08-16 00:51:10 +04:00
* We are under @ sbp - > s_lock .
2005-04-17 02:20:36 +04:00
*/
static int vxfs_fill_super ( struct super_block * sbp , void * dp , int silent )
{
struct vxfs_sb_info * infp ;
struct vxfs_sb * rsbp ;
struct buffer_head * bp = NULL ;
u_long bsize ;
struct inode * root ;
2008-02-07 11:15:39 +03:00
int ret = - EINVAL ;
2005-04-17 02:20:36 +04:00
sbp - > s_flags | = MS_RDONLY ;
2005-09-07 02:18:35 +04:00
infp = kzalloc ( sizeof ( * infp ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! infp ) {
printk ( KERN_WARNING " vxfs: unable to allocate incore superblock \n " ) ;
return - ENOMEM ;
}
bsize = sb_min_blocksize ( sbp , BLOCK_SIZE ) ;
if ( ! bsize ) {
printk ( KERN_WARNING " vxfs: unable to set blocksize \n " ) ;
goto out ;
}
bp = sb_bread ( sbp , 1 ) ;
if ( ! bp | | ! buffer_mapped ( bp ) ) {
if ( ! silent ) {
printk ( KERN_WARNING
" vxfs: unable to read disk superblock \n " ) ;
}
goto out ;
}
rsbp = ( struct vxfs_sb * ) bp - > b_data ;
if ( rsbp - > vs_magic ! = VXFS_SUPER_MAGIC ) {
if ( ! silent )
printk ( KERN_NOTICE " vxfs: WRONG superblock magic \n " ) ;
goto out ;
}
if ( ( rsbp - > vs_version < 2 | | rsbp - > vs_version > 4 ) & & ! silent ) {
printk ( KERN_NOTICE " vxfs: unsupported VxFS version (%d) \n " ,
rsbp - > vs_version ) ;
goto out ;
}
# ifdef DIAGNOSTIC
printk ( KERN_DEBUG " vxfs: supported VxFS version (%d) \n " , rsbp - > vs_version ) ;
printk ( KERN_DEBUG " vxfs: blocksize: %d \n " , rsbp - > vs_bsize ) ;
# endif
sbp - > s_magic = rsbp - > vs_magic ;
2005-06-30 13:59:05 +04:00
sbp - > s_fs_info = infp ;
2005-04-17 02:20:36 +04:00
infp - > vsi_raw = rsbp ;
infp - > vsi_bp = bp ;
infp - > vsi_oltext = rsbp - > vs_oltext [ 0 ] ;
infp - > vsi_oltsize = rsbp - > vs_oltsize ;
if ( ! sb_set_blocksize ( sbp , rsbp - > vs_bsize ) ) {
printk ( KERN_WARNING " vxfs: unable to set final block size \n " ) ;
goto out ;
}
if ( vxfs_read_olt ( sbp , bsize ) ) {
printk ( KERN_WARNING " vxfs: unable to read olt \n " ) ;
goto out ;
}
if ( vxfs_read_fshead ( sbp ) ) {
printk ( KERN_WARNING " vxfs: unable to read fshead \n " ) ;
goto out ;
}
sbp - > s_op = & vxfs_super_ops ;
2008-02-07 11:15:39 +03:00
root = vxfs_iget ( sbp , VXFS_ROOT_INO ) ;
if ( IS_ERR ( root ) ) {
ret = PTR_ERR ( root ) ;
goto out ;
}
2012-01-09 07:15:13 +04:00
sbp - > s_root = d_make_root ( root ) ;
2005-04-17 02:20:36 +04:00
if ( ! sbp - > s_root ) {
printk ( KERN_WARNING " vxfs: unable to get root dentry. \n " ) ;
goto out_free_ilist ;
}
return 0 ;
out_free_ilist :
vxfs_put_fake_inode ( infp - > vsi_fship ) ;
vxfs_put_fake_inode ( infp - > vsi_ilist ) ;
vxfs_put_fake_inode ( infp - > vsi_stilist ) ;
out :
brelse ( bp ) ;
kfree ( infp ) ;
2008-02-07 11:15:39 +03:00
return ret ;
2005-04-17 02:20:36 +04:00
}
/*
* The usual module blurb .
*/
2010-07-25 00:46:55 +04:00
static struct dentry * vxfs_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 , vxfs_fill_super ) ;
2005-04-17 02:20:36 +04:00
}
static struct file_system_type vxfs_fs_type = {
. owner = THIS_MODULE ,
. name = " vxfs " ,
2010-07-25 00:46:55 +04:00
. mount = vxfs_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 ( " vxfs " ) ; /* makes mount -t vxfs autoload the module */
2013-03-13 05:27:41 +04:00
MODULE_ALIAS ( " vxfs " ) ;
2005-04-17 02:20:36 +04:00
static int __init
vxfs_init ( void )
{
2006-09-29 13:01:04 +04:00
int rv ;
2005-04-17 02:20:36 +04:00
vxfs_inode_cachep = kmem_cache_create ( " vxfs_inode " ,
2007-07-20 05:11:58 +04:00
sizeof ( struct vxfs_inode_info ) , 0 ,
SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD , NULL ) ;
2006-09-29 13:01:04 +04:00
if ( ! vxfs_inode_cachep )
return - ENOMEM ;
rv = register_filesystem ( & vxfs_fs_type ) ;
if ( rv < 0 )
kmem_cache_destroy ( vxfs_inode_cachep ) ;
return rv ;
2005-04-17 02:20:36 +04:00
}
static void __exit
vxfs_cleanup ( void )
{
unregister_filesystem ( & vxfs_fs_type ) ;
2012-09-26 05:33:07 +04:00
/*
* Make sure all delayed rcu free inodes are flushed before we
* destroy cache .
*/
rcu_barrier ( ) ;
2005-04-17 02:20:36 +04:00
kmem_cache_destroy ( vxfs_inode_cachep ) ;
}
module_init ( vxfs_init ) ;
module_exit ( vxfs_cleanup ) ;