2001-09-18 19:38:54 +04:00
/*
* dmfs - super . c
*
* Copyright ( C ) 2001 Sistina Software
*
* This software is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation ; either version 2 , or ( at
* your option ) any later version .
*
* This software is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with GNU CC ; see the file COPYING . If not , write to
* the Free Software Foundation , 59 Temple Place - Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
*/
# include <linux/config.h>
# include <linux/fs.h>
2001-11-07 15:12:56 +03:00
# include <linux/init.h>
2001-09-18 19:38:54 +04:00
2001-11-07 15:12:56 +03:00
# include "dmfs.h"
2001-10-11 01:49:21 +04:00
# include "dm.h"
2001-09-18 19:38:54 +04:00
# define DMFS_MAGIC 0x444D4653
2001-09-26 13:26:10 +04:00
extern struct inode * dmfs_create_root ( struct super_block * sb , int ) ;
2001-09-18 19:38:54 +04:00
static int dmfs_statfs ( struct super_block * sb , struct statfs * buf )
{
buf - > f_type = sb - > s_magic ;
buf - > f_bsize = sb - > s_blocksize ;
buf - > f_namelen = DM_NAME_LEN - 1 ;
return 0 ;
}
2001-09-18 20:54:14 +04:00
static void dmfs_delete_inode ( struct inode * inode )
2001-09-18 19:38:54 +04:00
{
2001-10-05 14:00:13 +04:00
struct dmfs_i * dmi = DMFS_I ( inode ) ;
2001-09-18 19:38:54 +04:00
2001-10-05 14:00:13 +04:00
if ( dmi ) {
if ( dmi - > md )
dm_remove ( dmi - > md ) ;
if ( dmi - > table )
2001-10-15 20:40:17 +04:00
dm_table_destroy ( dmi - > table ) ;
2001-10-05 14:00:13 +04:00
if ( dmi - > dentry )
2001-10-15 20:40:17 +04:00
dput ( dmi - > dentry ) ;
2001-10-24 12:26:10 +04:00
if ( ! list_empty ( & dmi - > errors ) )
dmfs_zap_errors ( inode ) ;
2001-10-05 14:00:13 +04:00
kfree ( dmi ) ;
2001-11-10 20:11:36 +03:00
MOD_DEC_USE_COUNT ; /* Don't remove */
2001-09-18 19:38:54 +04:00
}
2001-09-19 20:01:27 +04:00
inode - > u . generic_ip = NULL ;
2001-09-18 19:38:54 +04:00
clear_inode ( inode ) ;
}
static struct super_operations dmfs_super_operations = {
statfs : dmfs_statfs ,
put_inode : force_delete ,
delete_inode : dmfs_delete_inode ,
} ;
2001-11-07 15:12:56 +03:00
static struct super_block * dmfs_read_super ( struct super_block * sb , void * data , int silent )
2001-09-18 19:38:54 +04:00
{
struct inode * inode ;
struct dentry * root ;
sb - > s_blocksize = PAGE_CACHE_SIZE ;
sb - > s_blocksize_bits = PAGE_CACHE_SHIFT ;
sb - > s_magic = DMFS_MAGIC ;
2001-10-12 14:06:40 +04:00
sb - > s_op = & dmfs_super_operations ;
2001-09-18 19:38:54 +04:00
sb - > s_maxbytes = MAX_NON_LFS ;
inode = dmfs_create_root ( sb , 0755 ) ;
if ( IS_ERR ( inode ) )
return NULL ;
root = d_alloc_root ( inode ) ;
if ( ! root ) {
iput ( inode ) ;
return NULL ;
}
sb - > s_root = root ;
return sb ;
}
2001-10-11 01:49:21 +04:00
struct inode * dmfs_new_inode ( struct super_block * sb , int mode )
{
struct inode * inode = new_inode ( sb ) ;
if ( inode ) {
inode - > i_mode = mode ;
inode - > i_uid = current - > fsuid ;
inode - > i_gid = current - > fsgid ;
inode - > i_blksize = PAGE_CACHE_SIZE ;
inode - > i_blocks = 0 ;
inode - > i_rdev = NODEV ;
inode - > i_atime = inode - > i_ctime = inode - > i_mtime = CURRENT_TIME ;
2001-11-07 15:12:56 +03:00
}
return inode ;
}
struct inode * dmfs_new_private_inode ( struct super_block * sb , int mode )
{
struct inode * inode = dmfs_new_inode ( sb , mode ) ;
struct dmfs_i * dmi ;
2001-09-18 19:38:54 +04:00
2001-11-07 15:12:56 +03:00
if ( inode ) {
2001-10-11 01:49:21 +04:00
dmi = kmalloc ( sizeof ( struct dmfs_i ) , GFP_KERNEL ) ;
if ( dmi = = NULL ) {
iput ( inode ) ;
return NULL ;
}
2001-10-16 02:39:14 +04:00
memset ( dmi , 0 , sizeof ( struct dmfs_i ) ) ;
2001-10-11 01:49:21 +04:00
init_MUTEX ( & dmi - > sem ) ;
2001-10-24 12:26:10 +04:00
INIT_LIST_HEAD ( & dmi - > errors ) ;
2001-10-12 14:06:40 +04:00
inode - > u . generic_ip = dmi ;
2001-11-10 20:11:36 +03:00
MOD_INC_USE_COUNT ; /* Don't remove */
2001-10-11 01:49:21 +04:00
}
return inode ;
}
2001-11-07 15:12:56 +03:00
static DECLARE_FSTYPE ( dmfs_fstype , " dmfs " , dmfs_read_super , FS_SINGLE ) ;
static struct vfsmount * dmfs_mnt ;
int __init dmfs_init ( void )
{
int ret ;
ret = register_filesystem ( & dmfs_fstype ) ;
if ( ret < 0 )
goto out ;
dmfs_mnt = kern_mount ( & dmfs_fstype ) ;
if ( IS_ERR ( dmfs_mnt ) ) {
ret = PTR_ERR ( dmfs_mnt ) ;
unregister_filesystem ( & dmfs_fstype ) ;
2001-11-10 20:11:36 +03:00
} else {
MOD_DEC_USE_COUNT ; /* Yes, this really is correct... */
2001-11-07 15:12:56 +03:00
}
out :
return ret ;
}
int __exit dmfs_exit ( void )
{
2001-11-10 20:11:36 +03:00
MOD_INC_USE_COUNT ; /* So that it lands up being zero */
do_umount ( dmfs_mnt , 0 ) ;
2001-11-07 15:12:56 +03:00
unregister_filesystem ( & dmfs_fstype ) ;
return 0 ;
}