2001-08-20 12:03:02 +04:00
/*
2001-09-07 15:34:46 +04:00
* * very * heavily based on ramfs
2001-08-20 12:03:02 +04:00
*
* Copyright ( C ) 2001 Sistina Software
*
2001-09-07 15:34:46 +04:00
* This file is released under the GPL .
2001-08-20 12:03:02 +04:00
*/
2001-09-07 15:34:46 +04:00
# include <linux/module.h>
# include <linux/fs.h>
# include <linux/pagemap.h>
# include <linux/init.h>
# include <linux/string.h>
# include <linux/locks.h>
# include <linux/file.h>
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
# include <asm/uaccess.h>
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
# include "dm.h"
2001-08-21 19:24:02 +04:00
2001-09-13 23:41:46 +04:00
/* some magic number */
# define DM_MAGIC 0x444D4653
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
static struct super_operations dm_ops ;
static struct address_space_operations dm_aops ;
static struct file_operations dm_dir_operations ;
static struct file_operations dm_file_operations ;
static struct inode_operations dm_dir_inode_operations ;
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
struct vfsmount * _mnt ;
2001-08-20 17:45:43 +04:00
2001-09-14 17:27:58 +04:00
static int dmfs_unlink ( struct inode * dir , struct dentry * dentry ) ;
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
# define NOT_A_TABLE ((struct dm_table *) 1)
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
/*
* context for the line splitter and error function .
*/
struct line_c {
unsigned int line_num ;
loff_t next_read ;
char data [ MAX_TARGET_LINE ] ;
struct file * in ;
struct file * out ;
2001-08-20 17:45:43 +04:00
} ;
2001-08-20 12:03:02 +04:00
2001-09-14 00:10:14 +04:00
static int is_identifier ( const char * str , int len )
2001-09-13 23:41:46 +04:00
{
2001-09-17 20:55:31 +04:00
if ( len > DM_NAME_LEN - 1 )
return 0 ;
2001-09-13 23:41:46 +04:00
while ( len - - ) {
2001-09-14 01:50:38 +04:00
if ( ! isalnum ( * str ) & & * str ! = ' _ ' )
2001-09-13 23:41:46 +04:00
return 0 ;
str + + ;
}
return 1 ;
}
2001-09-07 15:34:46 +04:00
/*
* Grabs lines one at a time from the table file .
*/
int extract_line ( struct text_region * line , void * private )
2001-08-20 12:03:02 +04:00
{
2001-09-07 15:34:46 +04:00
struct line_c * lc = ( struct line_c * ) private ;
struct text_region text ;
ssize_t n ;
loff_t off = lc - > next_read ;
const char * read_begin ;
2001-09-14 16:27:57 +04:00
mm_segment_t fs ;
fs = get_fs ( ) ;
set_fs ( get_ds ( ) ) ;
2001-09-07 15:34:46 +04:00
2001-09-14 17:27:58 +04:00
n = lc - > in - > f_op - > read ( lc - > in , lc - > data , sizeof ( lc - > data ) , & off ) ;
2001-09-07 15:34:46 +04:00
2001-09-14 16:27:57 +04:00
set_fs ( fs ) ;
2001-09-07 15:34:46 +04:00
if ( n < = 0 )
return 0 ;
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
read_begin = text . b = lc - > data ;
text . e = lc - > data + n ;
if ( ! dm_get_line ( & text , line ) )
2001-08-20 12:03:02 +04:00
return 0 ;
2001-09-07 15:34:46 +04:00
lc - > line_num + + ;
lc - > next_read + = line - > e - read_begin ;
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
return 1 ;
}
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
static struct file * open_error_file ( struct file * table )
{
struct file * f ;
2001-09-19 00:03:00 +04:00
char * name , * buffer ;
int bufsize = PATH_MAX + 1 ;
if ( bufsize < PAGE_SIZE )
bufsize = PAGE_SIZE ;
/* Get space to append ".err" */
buffer = ( char * ) kmalloc ( bufsize + 4 , GFP_KERNEL ) ;
2001-09-17 20:55:31 +04:00
if ( ! buffer )
return 0 ;
2001-08-20 12:03:02 +04:00
2001-09-17 20:55:31 +04:00
/* Get path name */
2001-09-19 00:03:00 +04:00
name = d_path ( table - > f_dentry , table - > f_vfsmnt , buffer , bufsize ) ;
2001-08-20 12:03:02 +04:00
2001-09-17 20:55:31 +04:00
if ( ! name ) {
kfree ( buffer ) ;
2001-09-07 15:34:46 +04:00
return 0 ;
2001-09-17 20:55:31 +04:00
}
2001-08-20 17:45:43 +04:00
2001-09-17 20:55:31 +04:00
/* Create error file */
strcat ( name , " .err " ) ;
2001-09-14 17:27:58 +04:00
f = filp_open ( name , O_WRONLY | O_TRUNC | O_CREAT , S_IRUGO ) ;
2001-09-17 20:55:31 +04:00
kfree ( buffer ) ;
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
if ( f )
f - > f_dentry - > d_inode - > u . generic_ip = NOT_A_TABLE ;
return f ;
2001-08-20 12:03:02 +04:00
}
2001-09-07 15:34:46 +04:00
static void close_error_file ( struct file * out )
2001-08-20 12:03:02 +04:00
{
2001-09-07 15:34:46 +04:00
fput ( out ) ;
}
2001-09-20 22:22:35 +04:00
static void parse_error ( const char * message , struct line_c * lc )
2001-09-07 15:34:46 +04:00
{
char buffer [ 32 ] ;
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
# define emit(b, l) lc->out->f_op->write(lc->out, (b), (l), &lc->out->f_pos)
emit ( lc - > in - > f_dentry - > d_name . name , lc - > in - > f_dentry - > d_name . len ) ;
sprintf ( buffer , " (%d): " , lc - > line_num ) ;
emit ( buffer , strlen ( buffer ) ) ;
emit ( message , strlen ( message ) ) ;
emit ( " \n " , 1 ) ;
# undef emit
2001-08-20 17:45:43 +04:00
}
2001-08-20 12:03:02 +04:00
2001-09-14 17:27:58 +04:00
static int dmfs_release ( struct inode * inode , struct file * f )
2001-08-22 19:01:09 +04:00
{
2001-09-07 15:34:46 +04:00
/* FIXME: we should lock the inode to
2001-09-14 17:27:58 +04:00
prevent someone else opening it while
we are parsing */
2001-09-07 15:34:46 +04:00
struct line_c * lc ;
struct dm_table * table = ( struct dm_table * ) inode - > u . generic_ip ;
/* noop for files without tables (.err files) */
if ( table = = NOT_A_TABLE )
return 0 ;
2001-08-22 19:01:09 +04:00
2001-09-07 15:34:46 +04:00
/* only bother parsing if it was open for a write */
if ( ! ( f - > f_mode & S_IWUGO ) )
return 0 ;
2001-08-22 19:01:09 +04:00
2001-09-07 15:34:46 +04:00
/* free off the old table */
if ( table ) {
2001-09-19 20:01:27 +04:00
dm_put_table ( table ) ;
2001-09-07 15:34:46 +04:00
inode - > u . generic_ip = 0 ;
}
2001-08-22 19:01:09 +04:00
2001-09-14 17:27:58 +04:00
if ( ! ( lc = kmalloc ( sizeof ( * lc ) , GFP_KERNEL ) ) )
2001-08-22 19:01:09 +04:00
return - ENOMEM ;
2001-09-14 17:27:58 +04:00
memset ( lc , 0 , sizeof ( * lc ) ) ;
2001-09-07 15:34:46 +04:00
lc - > in = f ;
2001-08-22 19:01:09 +04:00
2001-09-14 15:15:54 +04:00
if ( ! ( lc - > out = open_error_file ( lc - > in ) ) )
return - ENOMEM ;
2001-09-20 22:22:35 +04:00
table = dm_parse ( extract_line , lc ) ;
if ( table & & table - > err_msg )
parse_error ( table - > err_msg , lc ) ;
2001-08-22 19:33:08 +04:00
2001-09-14 15:15:54 +04:00
close_error_file ( lc - > out ) ;
2001-09-07 15:34:46 +04:00
kfree ( lc ) ;
inode - > u . generic_ip = table ;
2001-08-22 19:33:08 +04:00
2001-08-22 19:01:09 +04:00
return 0 ;
}
2001-09-14 17:27:58 +04:00
void dmfs_put_inode ( struct inode * inode )
2001-08-22 19:01:09 +04:00
{
2001-09-14 17:27:58 +04:00
struct mapped_device * md = ( struct mapped_device * ) inode - > u . generic_ip ;
2001-09-07 15:34:46 +04:00
struct dm_table * table = ( struct dm_table * ) inode - > u . generic_ip ;
2001-08-31 19:13:33 +04:00
2001-09-07 15:34:46 +04:00
if ( inode - > i_mode & S_IFDIR ) {
if ( md )
2001-09-18 20:52:50 +04:00
dm_remove ( md ) ;
2001-09-07 15:34:46 +04:00
} else {
if ( table )
2001-09-19 20:01:27 +04:00
dm_put_table ( table ) ;
2001-08-31 19:13:33 +04:00
2001-08-22 19:01:09 +04:00
}
2001-08-22 19:33:08 +04:00
2001-09-07 15:34:46 +04:00
inode - > u . generic_ip = 0 ;
force_delete ( inode ) ;
2001-08-22 19:01:09 +04:00
}
2001-09-14 17:27:58 +04:00
static int dmfs_statfs ( struct super_block * sb , struct statfs * buf )
2001-08-20 12:03:02 +04:00
{
2001-09-07 15:34:46 +04:00
buf - > f_type = DM_MAGIC ;
buf - > f_bsize = PAGE_CACHE_SIZE ;
buf - > f_namelen = 255 ;
return 0 ;
}
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
/*
* Lookup the data . This is trivial - if the dentry didn ' t already
* exist , we know it is negative .
*/
2001-09-14 17:27:58 +04:00
static struct dentry * dmfs_lookup ( struct inode * dir , struct dentry * dentry )
2001-09-07 15:34:46 +04:00
{
d_add ( dentry , NULL ) ;
return NULL ;
}
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
/*
* Read a page . Again trivial . If it didn ' t already exist
* in the page cache , it is zero - filled .
*/
2001-09-14 17:27:58 +04:00
static int dmfs_readpage ( struct file * file , struct page * page )
2001-09-07 15:34:46 +04:00
{
if ( ! Page_Uptodate ( page ) ) {
memset ( kmap ( page ) , 0 , PAGE_CACHE_SIZE ) ;
kunmap ( page ) ;
flush_dcache_page ( page ) ;
SetPageUptodate ( page ) ;
}
UnlockPage ( page ) ;
return 0 ;
}
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
/*
* Writing : just make sure the page gets marked dirty , so that
* the page stealer won ' t grab it .
*/
2001-09-14 17:27:58 +04:00
static int dmfs_writepage ( struct page * page )
2001-09-07 15:34:46 +04:00
{
SetPageDirty ( page ) ;
UnlockPage ( page ) ;
return 0 ;
}
2001-08-20 12:03:02 +04:00
2001-09-14 17:27:58 +04:00
static int dmfs_prepare_write ( struct file * file , struct page * page ,
unsigned offset , unsigned to )
2001-09-07 15:34:46 +04:00
{
void * addr = kmap ( page ) ;
if ( ! Page_Uptodate ( page ) ) {
memset ( addr , 0 , PAGE_CACHE_SIZE ) ;
flush_dcache_page ( page ) ;
SetPageUptodate ( page ) ;
}
SetPageDirty ( page ) ;
return 0 ;
}
2001-08-20 12:03:02 +04:00
2001-09-14 17:27:58 +04:00
static int dmfs_commit_write ( struct file * file , struct page * page ,
unsigned offset , unsigned to )
2001-09-07 15:34:46 +04:00
{
struct inode * inode = page - > mapping - > host ;
2001-09-14 17:27:58 +04:00
loff_t pos = ( ( loff_t ) page - > index < < PAGE_CACHE_SHIFT ) + to ;
2001-08-22 19:01:09 +04:00
2001-09-07 15:34:46 +04:00
kunmap ( page ) ;
if ( pos > inode - > i_size )
inode - > i_size = pos ;
return 0 ;
}
2001-08-20 12:03:02 +04:00
2001-09-14 17:27:58 +04:00
struct inode * dmfs_get_inode ( struct super_block * sb , int mode , int dev )
2001-09-07 15:34:46 +04:00
{
2001-09-14 17:27:58 +04:00
struct inode * inode = new_inode ( sb ) ;
2001-09-07 15:34:46 +04:00
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_mapping - > a_ops = & dm_aops ;
2001-09-14 17:27:58 +04:00
inode - > i_atime = inode - > i_mtime = inode - > i_ctime = CURRENT_TIME ;
2001-09-07 15:34:46 +04:00
switch ( mode & S_IFMT ) {
2001-09-13 23:41:46 +04:00
case S_IFBLK :
case S_IFCHR :
2001-09-07 15:34:46 +04:00
init_special_inode ( inode , mode , dev ) ;
break ;
case S_IFREG :
inode - > i_fop = & dm_file_operations ;
break ;
case S_IFDIR :
inode - > i_op = & dm_dir_inode_operations ;
inode - > i_fop = & dm_dir_operations ;
break ;
case S_IFLNK :
inode - > i_op = & page_symlink_inode_operations ;
break ;
2001-09-13 23:41:46 +04:00
default :
make_bad_inode ( inode ) ;
2001-08-20 17:45:43 +04:00
}
2001-09-07 15:34:46 +04:00
}
return inode ;
}
2001-08-21 19:24:02 +04:00
2001-09-07 15:34:46 +04:00
/*
* File creation . Allocate an inode , and we ' re done . .
*/
2001-09-14 17:27:58 +04:00
static int dmfs_mknod ( struct inode * dir , struct dentry * dentry , int mode )
2001-09-07 15:34:46 +04:00
{
int error = - ENOSPC ;
2001-09-14 17:27:58 +04:00
struct inode * inode = dmfs_get_inode ( dir - > i_sb , mode , 0 ) ;
2001-09-07 15:34:46 +04:00
if ( inode ) {
d_instantiate ( dentry , inode ) ;
dget ( dentry ) ; /* Extra count - pin the dentry in core */
error = 0 ;
2001-08-20 12:03:02 +04:00
}
2001-09-07 15:34:46 +04:00
return error ;
2001-08-20 12:03:02 +04:00
}
2001-09-14 17:27:58 +04:00
static int dmfs_mkdir ( struct inode * dir , struct dentry * dentry , int mode )
2001-08-20 12:03:02 +04:00
{
2001-08-23 16:35:02 +04:00
int r ;
2001-09-07 15:34:46 +04:00
const char * name = ( const char * ) dentry - > d_name . name ;
2001-09-18 20:52:50 +04:00
struct mapped_device * md ;
2001-08-20 12:03:02 +04:00
2001-09-13 23:41:46 +04:00
if ( ! is_identifier ( name , dentry - > d_name . len ) )
2001-09-14 17:27:58 +04:00
return - EPERM ; /* or EINVAL ? */
2001-09-13 23:41:46 +04:00
2001-09-18 20:52:50 +04:00
md = dm_create ( name , - 1 ) ;
if ( IS_ERR ( md ) )
return PTR_ERR ( md ) ;
2001-08-20 12:03:02 +04:00
2001-09-14 17:27:58 +04:00
r = dmfs_mknod ( dir , dentry , mode | S_IFDIR ) ;
2001-09-07 15:34:46 +04:00
if ( r ) {
2001-09-18 20:52:50 +04:00
dm_remove ( md ) ;
2001-09-07 15:34:46 +04:00
return r ;
}
2001-08-20 17:45:43 +04:00
2001-09-18 20:52:50 +04:00
dentry - > d_inode - > u . generic_ip = md ;
md - > inode = dentry - > d_inode ;
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
return 0 ;
}
2001-08-20 12:03:02 +04:00
2001-09-14 17:27:58 +04:00
static int dmfs_rmdir ( struct inode * dir , struct dentry * dentry )
2001-09-07 15:34:46 +04:00
{
2001-09-14 17:27:58 +04:00
int r = dmfs_unlink ( dir , dentry ) ;
2001-09-18 20:52:50 +04:00
return r ;
2001-09-07 15:34:46 +04:00
}
2001-08-20 17:45:43 +04:00
2001-09-14 17:27:58 +04:00
static int dmfs_create ( struct inode * dir , struct dentry * dentry , int mode )
2001-09-07 15:34:46 +04:00
{
int r ;
2001-08-20 17:45:43 +04:00
2001-09-14 17:27:58 +04:00
if ( ( r = dmfs_mknod ( dir , dentry , mode | S_IFREG ) ) )
2001-09-07 15:34:46 +04:00
return r ;
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
dentry - > d_inode - > u . generic_ip = 0 ;
return 0 ;
}
2001-08-20 17:45:43 +04:00
2001-09-13 23:41:46 +04:00
static inline int positive ( struct dentry * dentry )
2001-09-07 15:34:46 +04:00
{
return dentry - > d_inode & & ! d_unhashed ( dentry ) ;
}
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
/*
* Check that a directory is empty ( this works
* for regular files too , they ' ll just always be
* considered empty . . ) .
*
* Note that an empty directory can still have
* children , they just all have to be negative . .
*/
static int _empty ( struct dentry * dentry )
{
struct list_head * list ;
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
spin_lock ( & dcache_lock ) ;
list = dentry - > d_subdirs . next ;
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
while ( list ! = & dentry - > d_subdirs ) {
struct dentry * de = list_entry ( list , struct dentry , d_child ) ;
2001-08-20 17:45:43 +04:00
2001-09-13 23:41:46 +04:00
if ( positive ( de ) ) {
2001-09-07 15:34:46 +04:00
spin_unlock ( & dcache_lock ) ;
return 0 ;
2001-08-31 20:36:56 +04:00
}
2001-09-07 15:34:46 +04:00
list = list - > next ;
2001-08-23 16:35:02 +04:00
}
2001-09-07 15:34:46 +04:00
spin_unlock ( & dcache_lock ) ;
return 1 ;
}
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
/*
* This works for both directories and regular files .
* ( non - directories will always have empty subdirs )
*/
2001-09-14 17:27:58 +04:00
static int dmfs_unlink ( struct inode * dir , struct dentry * dentry )
2001-09-07 15:34:46 +04:00
{
int retval = - ENOTEMPTY ;
if ( _empty ( dentry ) ) {
struct inode * inode = dentry - > d_inode ;
inode - > i_nlink - - ;
dput ( dentry ) ; /* Undo the count from "create" - this does all the work */
retval = 0 ;
}
return retval ;
2001-08-20 17:45:43 +04:00
}
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
/*
* The VFS layer already does all the dentry stuff for rename ,
* we just have to decrement the usage count for the target if
* it exists so that the VFS layer correctly free ' s it when it
* gets overwritten .
*/
2001-09-14 17:27:58 +04:00
static int dmfs_rename ( struct inode * old_dir , struct dentry * old_dentry ,
struct inode * new_dir , struct dentry * new_dentry )
2001-08-20 17:45:43 +04:00
{
2001-09-07 15:34:46 +04:00
struct inode * inode = new_dentry - > d_inode ;
struct mapped_device * md = old_dir - > u . generic_ip ;
struct dm_table * table = old_dentry - > d_inode - > u . generic_ip ;
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
if ( ! md | | ! table )
return - EINVAL ;
if ( ! _empty ( new_dentry ) )
return - ENOTEMPTY ;
if ( ! strcmp ( new_dentry - > d_name . name , " ACTIVE " ) ) {
/* activate the table */
dm_activate ( md , table ) ;
} else if ( ! strcmp ( old_dentry - > d_name . name , " ACTIVE " ) ) {
dm_suspend ( md ) ;
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
}
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
if ( inode ) {
inode - > i_nlink - - ;
dput ( new_dentry ) ;
2001-08-20 12:03:02 +04:00
}
2001-09-07 15:34:46 +04:00
return 0 ;
2001-08-20 17:45:43 +04:00
}
2001-09-14 17:27:58 +04:00
static int dmfs_sync_file ( struct file * file , struct dentry * dentry ,
int datasync )
2001-08-20 17:45:43 +04:00
{
2001-09-07 15:34:46 +04:00
return 0 ;
}
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
static struct address_space_operations dm_aops = {
2001-09-14 17:27:58 +04:00
readpage : dmfs_readpage ,
writepage : dmfs_writepage ,
prepare_write : dmfs_prepare_write ,
commit_write : dmfs_commit_write
2001-09-07 15:34:46 +04:00
} ;
static struct file_operations dm_file_operations = {
read : generic_file_read ,
write : generic_file_write ,
mmap : generic_file_mmap ,
2001-09-14 17:27:58 +04:00
fsync : dmfs_sync_file ,
release : dmfs_release ,
2001-09-07 15:34:46 +04:00
} ;
static struct file_operations dm_dir_operations = {
read : generic_read_dir ,
readdir : dcache_readdir ,
2001-09-14 17:27:58 +04:00
fsync : dmfs_sync_file ,
2001-09-07 15:34:46 +04:00
} ;
2001-08-20 17:45:43 +04:00
2001-09-07 15:34:46 +04:00
static struct inode_operations root_dir_inode_operations = {
2001-09-14 17:27:58 +04:00
lookup : dmfs_lookup ,
mkdir : dmfs_mkdir ,
rmdir : dmfs_rmdir ,
rename : dmfs_rename ,
2001-09-07 15:34:46 +04:00
} ;
static struct inode_operations dm_dir_inode_operations = {
2001-09-14 17:27:58 +04:00
create : dmfs_create ,
lookup : dmfs_lookup ,
unlink : dmfs_unlink ,
rename : dmfs_rename ,
2001-09-07 15:34:46 +04:00
} ;
static struct super_operations dm_ops = {
2001-09-14 17:27:58 +04:00
statfs : dmfs_statfs ,
put_inode : dmfs_put_inode ,
2001-09-07 15:34:46 +04:00
} ;
2001-09-14 17:27:58 +04:00
static struct super_block * dmfs_read_super ( struct super_block * sb , void * data ,
int silent )
2001-09-07 15:34:46 +04:00
{
2001-09-14 17:27:58 +04:00
struct inode * inode ;
struct dentry * root ;
2001-09-07 15:34:46 +04:00
sb - > s_blocksize = PAGE_CACHE_SIZE ;
sb - > s_blocksize_bits = PAGE_CACHE_SHIFT ;
sb - > s_magic = DM_MAGIC ;
sb - > s_op = & dm_ops ;
2001-09-14 17:27:58 +04:00
inode = dmfs_get_inode ( sb , S_IFDIR | 0755 , 0 ) ;
2001-09-07 15:34:46 +04:00
inode - > i_op = & root_dir_inode_operations ;
if ( ! inode )
return NULL ;
root = d_alloc_root ( inode ) ;
if ( ! root ) {
iput ( inode ) ;
return NULL ;
2001-08-20 17:45:43 +04:00
}
2001-09-07 15:34:46 +04:00
sb - > s_root = root ;
return sb ;
}
2001-08-20 17:45:43 +04:00
2001-09-14 17:27:58 +04:00
static DECLARE_FSTYPE ( _fs_type , " dmfs " , dmfs_read_super , FS_SINGLE ) ;
2001-08-20 17:45:43 +04:00
2001-09-14 17:27:58 +04:00
int __init dmfs_init ( void )
2001-09-07 15:34:46 +04:00
{
int r ;
if ( ( r = register_filesystem ( & _fs_type ) ) )
return r ;
_mnt = kern_mount ( & _fs_type ) ;
if ( IS_ERR ( _mnt ) ) {
2001-09-14 17:27:58 +04:00
dmfs_exit ( ) ;
2001-09-07 15:34:46 +04:00
return PTR_ERR ( _mnt ) ;
}
2001-08-20 12:03:02 +04:00
2001-09-07 15:34:46 +04:00
return 0 ;
2001-08-20 12:03:02 +04:00
}
2001-08-21 19:24:02 +04:00
2001-09-14 17:27:58 +04:00
void __exit dmfs_exit ( void )
2001-09-07 15:34:46 +04:00
{
unregister_filesystem ( & _fs_type ) ;
}