2005-04-17 02:20:36 +04:00
/*
* vfsv0 quota IO operations on file
*/
# include <linux/errno.h>
# include <linux/fs.h>
# include <linux/mount.h>
# include <linux/dqblk_v2.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/slab.h>
2008-07-25 12:46:51 +04:00
# include <linux/quotaops.h>
2005-04-17 02:20:36 +04:00
# include <asm/byteorder.h>
2008-09-22 07:54:49 +04:00
# include "quota_tree.h"
2008-09-22 01:17:53 +04:00
# include "quotaio_v2.h"
2005-04-17 02:20:36 +04:00
MODULE_AUTHOR ( " Jan Kara " ) ;
MODULE_DESCRIPTION ( " Quota format v2 support " ) ;
MODULE_LICENSE ( " GPL " ) ;
# define __QUOTA_V2_PARANOIA
2009-11-16 20:09:47 +03:00
static void v2r0_mem2diskdqb ( void * dp , struct dquot * dquot ) ;
static void v2r0_disk2memdqb ( struct dquot * dquot , void * dp ) ;
static int v2r0_is_id ( void * dp , struct dquot * dquot ) ;
static void v2r1_mem2diskdqb ( void * dp , struct dquot * dquot ) ;
static void v2r1_disk2memdqb ( struct dquot * dquot , void * dp ) ;
static int v2r1_is_id ( void * dp , struct dquot * dquot ) ;
2016-01-01 10:53:37 +03:00
static const struct qtree_fmt_operations v2r0_qtree_ops = {
2009-11-16 20:09:47 +03:00
. mem2disk_dqblk = v2r0_mem2diskdqb ,
. disk2mem_dqblk = v2r0_disk2memdqb ,
. is_id = v2r0_is_id ,
} ;
2016-01-01 10:53:37 +03:00
static const struct qtree_fmt_operations v2r1_qtree_ops = {
2009-11-16 20:09:47 +03:00
. mem2disk_dqblk = v2r1_mem2diskdqb ,
. disk2mem_dqblk = v2r1_disk2memdqb ,
. is_id = v2r1_is_id ,
2008-09-22 07:54:49 +04:00
} ;
2005-04-17 02:20:36 +04:00
2008-08-20 16:45:12 +04:00
# define QUOTABLOCK_BITS 10
# define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
static inline qsize_t v2_stoqb ( qsize_t space )
{
return ( space + QUOTABLOCK_SIZE - 1 ) > > QUOTABLOCK_BITS ;
}
static inline qsize_t v2_qbtos ( qsize_t blocks )
{
return blocks < < QUOTABLOCK_BITS ;
}
2009-11-16 20:09:47 +03:00
static int v2_read_header ( struct super_block * sb , int type ,
struct v2_disk_dqheader * dqhead )
{
ssize_t size ;
size = sb - > s_op - > quota_read ( sb , type , ( char * ) dqhead ,
sizeof ( struct v2_disk_dqheader ) , 0 ) ;
if ( size ! = sizeof ( struct v2_disk_dqheader ) ) {
2010-07-20 18:54:43 +04:00
quota_error ( sb , " Failed header read: expected=%zd got=%zd " ,
sizeof ( struct v2_disk_dqheader ) , size ) ;
2017-08-17 20:20:28 +03:00
if ( size < 0 )
return size ;
return - EIO ;
2009-11-16 20:09:47 +03:00
}
2017-08-17 20:20:28 +03:00
return 0 ;
2009-11-16 20:09:47 +03:00
}
2005-04-17 02:20:36 +04:00
/* Check whether given file is really vfsv0 quotafile */
static int v2_check_quota_file ( struct super_block * sb , int type )
{
struct v2_disk_dqheader dqhead ;
static const uint quota_magics [ ] = V2_INITQMAGICS ;
static const uint quota_versions [ ] = V2_INITQVERSIONS ;
2017-08-17 20:20:28 +03:00
if ( v2_read_header ( sb , type , & dqhead ) )
2005-04-17 02:20:36 +04:00
return 0 ;
if ( le32_to_cpu ( dqhead . dqh_magic ) ! = quota_magics [ type ] | |
2009-11-16 20:09:47 +03:00
le32_to_cpu ( dqhead . dqh_version ) > quota_versions [ type ] )
2005-04-17 02:20:36 +04:00
return 0 ;
return 1 ;
}
/* Read information header from quota file */
static int v2_read_file_info ( struct super_block * sb , int type )
{
struct v2_disk_dqinfo dinfo ;
2009-11-16 20:09:47 +03:00
struct v2_disk_dqheader dqhead ;
2017-06-09 09:59:46 +03:00
struct quota_info * dqopt = sb_dqopt ( sb ) ;
struct mem_dqinfo * info = & dqopt - > info [ type ] ;
2008-10-02 20:44:14 +04:00
struct qtree_mem_dqinfo * qinfo ;
2005-04-17 02:20:36 +04:00
ssize_t size ;
2009-11-16 20:09:47 +03:00
unsigned int version ;
2017-06-09 09:59:46 +03:00
int ret ;
2009-11-16 20:09:47 +03:00
2017-06-09 09:59:46 +03:00
down_read ( & dqopt - > dqio_sem ) ;
2017-08-17 20:20:28 +03:00
ret = v2_read_header ( sb , type , & dqhead ) ;
if ( ret < 0 )
2017-06-09 09:59:46 +03:00
goto out ;
2009-11-16 20:09:47 +03:00
version = le32_to_cpu ( dqhead . dqh_version ) ;
2009-12-21 23:57:04 +03:00
if ( ( info - > dqi_fmt_id = = QFMT_VFS_V0 & & version ! = 0 ) | |
2017-06-09 09:59:46 +03:00
( info - > dqi_fmt_id = = QFMT_VFS_V1 & & version ! = 1 ) ) {
2017-06-09 10:04:47 +03:00
ret = - EINVAL ;
2017-06-09 09:59:46 +03:00
goto out ;
}
2005-04-17 02:20:36 +04:00
size = sb - > s_op - > quota_read ( sb , type , ( char * ) & dinfo ,
sizeof ( struct v2_disk_dqinfo ) , V2_DQINFOOFF ) ;
if ( size ! = sizeof ( struct v2_disk_dqinfo ) ) {
2010-07-20 18:54:43 +04:00
quota_error ( sb , " Can't read info structure " ) ;
2017-08-17 20:20:28 +03:00
if ( size < 0 )
ret = size ;
else
ret = - EIO ;
2017-06-09 09:59:46 +03:00
goto out ;
2005-04-17 02:20:36 +04:00
}
2008-10-02 20:44:14 +04:00
info - > dqi_priv = kmalloc ( sizeof ( struct qtree_mem_dqinfo ) , GFP_NOFS ) ;
if ( ! info - > dqi_priv ) {
2017-06-09 09:59:46 +03:00
ret = - ENOMEM ;
goto out ;
2008-10-02 20:44:14 +04:00
}
qinfo = info - > dqi_priv ;
2009-11-16 20:09:47 +03:00
if ( version = = 0 ) {
/* limits are stored as unsigned 32-bit data */
2015-03-04 16:42:02 +03:00
info - > dqi_max_spc_limit = 0xffffffffLL < < QUOTABLOCK_BITS ;
2014-10-09 18:54:13 +04:00
info - > dqi_max_ino_limit = 0xffffffff ;
2009-11-16 20:09:47 +03:00
} else {
2015-03-04 16:42:02 +03:00
/*
* Used space is stored as unsigned 64 - bit value in bytes but
* quota core supports only signed 64 - bit values so use that
* as a limit
*/
info - > dqi_max_spc_limit = 0x7fffffffffffffffLL ; /* 2^63-1 */
info - > dqi_max_ino_limit = 0x7fffffffffffffffLL ;
2009-11-16 20:09:47 +03:00
}
2005-04-17 02:20:36 +04:00
info - > dqi_bgrace = le32_to_cpu ( dinfo . dqi_bgrace ) ;
info - > dqi_igrace = le32_to_cpu ( dinfo . dqi_igrace ) ;
2014-11-19 11:03:28 +03:00
/* No flags currently supported */
info - > dqi_flags = 0 ;
2008-10-02 20:44:14 +04:00
qinfo - > dqi_sb = sb ;
qinfo - > dqi_type = type ;
qinfo - > dqi_blocks = le32_to_cpu ( dinfo . dqi_blocks ) ;
qinfo - > dqi_free_blk = le32_to_cpu ( dinfo . dqi_free_blk ) ;
qinfo - > dqi_free_entry = le32_to_cpu ( dinfo . dqi_free_entry ) ;
qinfo - > dqi_blocksize_bits = V2_DQBLKSIZE_BITS ;
qinfo - > dqi_usable_bs = 1 < < V2_DQBLKSIZE_BITS ;
qinfo - > dqi_qtree_depth = qtree_depth ( qinfo ) ;
2009-11-16 20:09:47 +03:00
if ( version = = 0 ) {
qinfo - > dqi_entry_size = sizeof ( struct v2r0_disk_dqblk ) ;
qinfo - > dqi_ops = & v2r0_qtree_ops ;
} else {
qinfo - > dqi_entry_size = sizeof ( struct v2r1_disk_dqblk ) ;
qinfo - > dqi_ops = & v2r1_qtree_ops ;
}
2017-06-09 09:59:46 +03:00
ret = 0 ;
out :
up_read ( & dqopt - > dqio_sem ) ;
return ret ;
2005-04-17 02:20:36 +04:00
}
/* Write information header to quota file */
static int v2_write_file_info ( struct super_block * sb , int type )
{
struct v2_disk_dqinfo dinfo ;
2017-06-09 09:45:43 +03:00
struct quota_info * dqopt = sb_dqopt ( sb ) ;
struct mem_dqinfo * info = & dqopt - > info [ type ] ;
2008-10-02 20:44:14 +04:00
struct qtree_mem_dqinfo * qinfo = info - > dqi_priv ;
2005-04-17 02:20:36 +04:00
ssize_t size ;
2017-06-09 09:45:43 +03:00
down_write ( & dqopt - > dqio_sem ) ;
2005-04-17 02:20:36 +04:00
spin_lock ( & dq_data_lock ) ;
info - > dqi_flags & = ~ DQF_INFO_DIRTY ;
dinfo . dqi_bgrace = cpu_to_le32 ( info - > dqi_bgrace ) ;
dinfo . dqi_igrace = cpu_to_le32 ( info - > dqi_igrace ) ;
2014-11-19 11:03:28 +03:00
/* No flags currently supported */
dinfo . dqi_flags = cpu_to_le32 ( 0 ) ;
2005-04-17 02:20:36 +04:00
spin_unlock ( & dq_data_lock ) ;
2008-10-02 20:44:14 +04:00
dinfo . dqi_blocks = cpu_to_le32 ( qinfo - > dqi_blocks ) ;
dinfo . dqi_free_blk = cpu_to_le32 ( qinfo - > dqi_free_blk ) ;
dinfo . dqi_free_entry = cpu_to_le32 ( qinfo - > dqi_free_entry ) ;
2005-04-17 02:20:36 +04:00
size = sb - > s_op - > quota_write ( sb , type , ( char * ) & dinfo ,
sizeof ( struct v2_disk_dqinfo ) , V2_DQINFOOFF ) ;
2017-06-09 09:45:43 +03:00
up_write ( & dqopt - > dqio_sem ) ;
2005-04-17 02:20:36 +04:00
if ( size ! = sizeof ( struct v2_disk_dqinfo ) ) {
2010-07-20 18:54:43 +04:00
quota_error ( sb , " Can't write info structure " ) ;
2005-04-17 02:20:36 +04:00
return - 1 ;
}
return 0 ;
}
2009-11-16 20:09:47 +03:00
static void v2r0_disk2memdqb ( struct dquot * dquot , void * dp )
2005-04-17 02:20:36 +04:00
{
2009-11-16 20:09:47 +03:00
struct v2r0_disk_dqblk * d = dp , empty ;
2008-09-22 07:54:49 +04:00
struct mem_dqblk * m = & dquot - > dq_dqb ;
2005-04-17 02:20:36 +04:00
m - > dqb_ihardlimit = le32_to_cpu ( d - > dqb_ihardlimit ) ;
m - > dqb_isoftlimit = le32_to_cpu ( d - > dqb_isoftlimit ) ;
m - > dqb_curinodes = le32_to_cpu ( d - > dqb_curinodes ) ;
m - > dqb_itime = le64_to_cpu ( d - > dqb_itime ) ;
2008-08-20 16:45:12 +04:00
m - > dqb_bhardlimit = v2_qbtos ( le32_to_cpu ( d - > dqb_bhardlimit ) ) ;
m - > dqb_bsoftlimit = v2_qbtos ( le32_to_cpu ( d - > dqb_bsoftlimit ) ) ;
2005-04-17 02:20:36 +04:00
m - > dqb_curspace = le64_to_cpu ( d - > dqb_curspace ) ;
m - > dqb_btime = le64_to_cpu ( d - > dqb_btime ) ;
2008-09-22 07:54:49 +04:00
/* We need to escape back all-zero structure */
2009-11-16 20:09:47 +03:00
memset ( & empty , 0 , sizeof ( struct v2r0_disk_dqblk ) ) ;
2008-09-22 07:54:49 +04:00
empty . dqb_itime = cpu_to_le64 ( 1 ) ;
2009-11-16 20:09:47 +03:00
if ( ! memcmp ( & empty , dp , sizeof ( struct v2r0_disk_dqblk ) ) )
2008-09-22 07:54:49 +04:00
m - > dqb_itime = 0 ;
2005-04-17 02:20:36 +04:00
}
2009-11-16 20:09:47 +03:00
static void v2r0_mem2diskdqb ( void * dp , struct dquot * dquot )
2005-04-17 02:20:36 +04:00
{
2009-11-16 20:09:47 +03:00
struct v2r0_disk_dqblk * d = dp ;
2008-09-22 07:54:49 +04:00
struct mem_dqblk * m = & dquot - > dq_dqb ;
struct qtree_mem_dqinfo * info =
2012-09-16 14:56:19 +04:00
sb_dqinfo ( dquot - > dq_sb , dquot - > dq_id . type ) - > dqi_priv ;
2008-09-22 07:54:49 +04:00
2005-04-17 02:20:36 +04:00
d - > dqb_ihardlimit = cpu_to_le32 ( m - > dqb_ihardlimit ) ;
d - > dqb_isoftlimit = cpu_to_le32 ( m - > dqb_isoftlimit ) ;
d - > dqb_curinodes = cpu_to_le32 ( m - > dqb_curinodes ) ;
d - > dqb_itime = cpu_to_le64 ( m - > dqb_itime ) ;
2008-09-22 01:17:53 +04:00
d - > dqb_bhardlimit = cpu_to_le32 ( v2_stoqb ( m - > dqb_bhardlimit ) ) ;
d - > dqb_bsoftlimit = cpu_to_le32 ( v2_stoqb ( m - > dqb_bsoftlimit ) ) ;
2005-04-17 02:20:36 +04:00
d - > dqb_curspace = cpu_to_le64 ( m - > dqb_curspace ) ;
d - > dqb_btime = cpu_to_le64 ( m - > dqb_btime ) ;
2012-09-16 14:56:19 +04:00
d - > dqb_id = cpu_to_le32 ( from_kqid ( & init_user_ns , dquot - > dq_id ) ) ;
2008-09-22 07:54:49 +04:00
if ( qtree_entry_unused ( info , dp ) )
d - > dqb_itime = cpu_to_le64 ( 1 ) ;
2005-04-17 02:20:36 +04:00
}
2009-11-16 20:09:47 +03:00
static int v2r0_is_id ( void * dp , struct dquot * dquot )
{
struct v2r0_disk_dqblk * d = dp ;
struct qtree_mem_dqinfo * info =
2012-09-16 14:56:19 +04:00
sb_dqinfo ( dquot - > dq_sb , dquot - > dq_id . type ) - > dqi_priv ;
2009-11-16 20:09:47 +03:00
if ( qtree_entry_unused ( info , dp ) )
return 0 ;
2012-09-16 14:56:19 +04:00
return qid_eq ( make_kqid ( & init_user_ns , dquot - > dq_id . type ,
le32_to_cpu ( d - > dqb_id ) ) ,
dquot - > dq_id ) ;
2009-11-16 20:09:47 +03:00
}
static void v2r1_disk2memdqb ( struct dquot * dquot , void * dp )
{
struct v2r1_disk_dqblk * d = dp , empty ;
struct mem_dqblk * m = & dquot - > dq_dqb ;
m - > dqb_ihardlimit = le64_to_cpu ( d - > dqb_ihardlimit ) ;
m - > dqb_isoftlimit = le64_to_cpu ( d - > dqb_isoftlimit ) ;
m - > dqb_curinodes = le64_to_cpu ( d - > dqb_curinodes ) ;
m - > dqb_itime = le64_to_cpu ( d - > dqb_itime ) ;
m - > dqb_bhardlimit = v2_qbtos ( le64_to_cpu ( d - > dqb_bhardlimit ) ) ;
m - > dqb_bsoftlimit = v2_qbtos ( le64_to_cpu ( d - > dqb_bsoftlimit ) ) ;
m - > dqb_curspace = le64_to_cpu ( d - > dqb_curspace ) ;
m - > dqb_btime = le64_to_cpu ( d - > dqb_btime ) ;
/* We need to escape back all-zero structure */
memset ( & empty , 0 , sizeof ( struct v2r1_disk_dqblk ) ) ;
empty . dqb_itime = cpu_to_le64 ( 1 ) ;
if ( ! memcmp ( & empty , dp , sizeof ( struct v2r1_disk_dqblk ) ) )
m - > dqb_itime = 0 ;
}
static void v2r1_mem2diskdqb ( void * dp , struct dquot * dquot )
{
struct v2r1_disk_dqblk * d = dp ;
struct mem_dqblk * m = & dquot - > dq_dqb ;
struct qtree_mem_dqinfo * info =
2012-09-16 14:56:19 +04:00
sb_dqinfo ( dquot - > dq_sb , dquot - > dq_id . type ) - > dqi_priv ;
2009-11-16 20:09:47 +03:00
d - > dqb_ihardlimit = cpu_to_le64 ( m - > dqb_ihardlimit ) ;
d - > dqb_isoftlimit = cpu_to_le64 ( m - > dqb_isoftlimit ) ;
d - > dqb_curinodes = cpu_to_le64 ( m - > dqb_curinodes ) ;
d - > dqb_itime = cpu_to_le64 ( m - > dqb_itime ) ;
d - > dqb_bhardlimit = cpu_to_le64 ( v2_stoqb ( m - > dqb_bhardlimit ) ) ;
d - > dqb_bsoftlimit = cpu_to_le64 ( v2_stoqb ( m - > dqb_bsoftlimit ) ) ;
d - > dqb_curspace = cpu_to_le64 ( m - > dqb_curspace ) ;
d - > dqb_btime = cpu_to_le64 ( m - > dqb_btime ) ;
2012-09-16 14:56:19 +04:00
d - > dqb_id = cpu_to_le32 ( from_kqid ( & init_user_ns , dquot - > dq_id ) ) ;
2009-11-16 20:09:47 +03:00
if ( qtree_entry_unused ( info , dp ) )
d - > dqb_itime = cpu_to_le64 ( 1 ) ;
}
static int v2r1_is_id ( void * dp , struct dquot * dquot )
2005-04-17 02:20:36 +04:00
{
2009-11-16 20:09:47 +03:00
struct v2r1_disk_dqblk * d = dp ;
2008-09-22 07:54:49 +04:00
struct qtree_mem_dqinfo * info =
2012-09-16 14:56:19 +04:00
sb_dqinfo ( dquot - > dq_sb , dquot - > dq_id . type ) - > dqi_priv ;
2005-04-17 02:20:36 +04:00
2008-09-22 07:54:49 +04:00
if ( qtree_entry_unused ( info , dp ) )
2005-04-17 02:20:36 +04:00
return 0 ;
2012-09-16 14:56:19 +04:00
return qid_eq ( make_kqid ( & init_user_ns , dquot - > dq_id . type ,
le32_to_cpu ( d - > dqb_id ) ) ,
dquot - > dq_id ) ;
2005-04-17 02:20:36 +04:00
}
2008-09-22 07:54:49 +04:00
static int v2_read_dquot ( struct dquot * dquot )
2005-04-17 02:20:36 +04:00
{
2017-06-08 16:30:45 +03:00
struct quota_info * dqopt = sb_dqopt ( dquot - > dq_sb ) ;
int ret ;
down_read ( & dqopt - > dqio_sem ) ;
ret = qtree_read_dquot (
sb_dqinfo ( dquot - > dq_sb , dquot - > dq_id . type ) - > dqi_priv ,
dquot ) ;
up_read ( & dqopt - > dqio_sem ) ;
return ret ;
2005-04-17 02:20:36 +04:00
}
static int v2_write_dquot ( struct dquot * dquot )
{
2017-06-08 16:48:16 +03:00
struct quota_info * dqopt = sb_dqopt ( dquot - > dq_sb ) ;
int ret ;
2017-06-08 17:09:46 +03:00
bool alloc = false ;
/*
* If space for dquot is already allocated , we don ' t need any
* protection as we ' ll only overwrite the place of dquot . We are
* still protected by concurrent writes of the same dquot by
* dquot - > dq_lock .
*/
if ( ! dquot - > dq_off ) {
alloc = true ;
down_write ( & dqopt - > dqio_sem ) ;
2017-09-26 11:36:05 +03:00
} else {
down_read ( & dqopt - > dqio_sem ) ;
2017-06-08 17:09:46 +03:00
}
2017-06-08 16:48:16 +03:00
ret = qtree_write_dquot (
sb_dqinfo ( dquot - > dq_sb , dquot - > dq_id . type ) - > dqi_priv ,
dquot ) ;
2017-06-08 17:09:46 +03:00
if ( alloc )
up_write ( & dqopt - > dqio_sem ) ;
2017-09-26 11:36:05 +03:00
else
up_read ( & dqopt - > dqio_sem ) ;
2017-06-08 16:48:16 +03:00
return ret ;
2005-04-17 02:20:36 +04:00
}
static int v2_release_dquot ( struct dquot * dquot )
{
2017-06-08 18:20:36 +03:00
struct quota_info * dqopt = sb_dqopt ( dquot - > dq_sb ) ;
int ret ;
down_write ( & dqopt - > dqio_sem ) ;
ret = qtree_release_dquot ( sb_dqinfo ( dquot - > dq_sb , dquot - > dq_id . type ) - > dqi_priv , dquot ) ;
up_write ( & dqopt - > dqio_sem ) ;
return ret ;
2008-10-02 20:44:14 +04:00
}
static int v2_free_file_info ( struct super_block * sb , int type )
{
kfree ( sb_dqinfo ( sb , type ) - > dqi_priv ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
2016-01-25 22:39:27 +03:00
static int v2_get_next_id ( struct super_block * sb , struct kqid * qid )
{
2017-06-09 09:36:16 +03:00
struct quota_info * dqopt = sb_dqopt ( sb ) ;
int ret ;
down_read ( & dqopt - > dqio_sem ) ;
ret = qtree_get_next_id ( sb_dqinfo ( sb , qid - > type ) - > dqi_priv , qid ) ;
up_read ( & dqopt - > dqio_sem ) ;
return ret ;
2016-01-25 22:39:27 +03:00
}
2009-10-16 15:26:03 +04:00
static const struct quota_format_ops v2_format_ops = {
2005-04-17 02:20:36 +04:00
. check_quota_file = v2_check_quota_file ,
. read_file_info = v2_read_file_info ,
. write_file_info = v2_write_file_info ,
2008-10-02 20:44:14 +04:00
. free_file_info = v2_free_file_info ,
2005-04-17 02:20:36 +04:00
. read_dqblk = v2_read_dquot ,
. commit_dqblk = v2_write_dquot ,
. release_dqblk = v2_release_dquot ,
2016-01-25 22:39:27 +03:00
. get_next_id = v2_get_next_id ,
2005-04-17 02:20:36 +04:00
} ;
2009-11-16 20:09:47 +03:00
static struct quota_format_type v2r0_quota_format = {
2005-04-17 02:20:36 +04:00
. qf_fmt_id = QFMT_VFS_V0 ,
. qf_ops = & v2_format_ops ,
. qf_owner = THIS_MODULE
} ;
2009-11-16 20:09:47 +03:00
static struct quota_format_type v2r1_quota_format = {
. qf_fmt_id = QFMT_VFS_V1 ,
. qf_ops = & v2_format_ops ,
. qf_owner = THIS_MODULE
} ;
2005-04-17 02:20:36 +04:00
static int __init init_v2_quota_format ( void )
{
2009-11-16 20:09:47 +03:00
int ret ;
ret = register_quota_format ( & v2r0_quota_format ) ;
if ( ret )
return ret ;
return register_quota_format ( & v2r1_quota_format ) ;
2005-04-17 02:20:36 +04:00
}
static void __exit exit_v2_quota_format ( void )
{
2009-11-16 20:09:47 +03:00
unregister_quota_format ( & v2r0_quota_format ) ;
unregister_quota_format ( & v2r1_quota_format ) ;
2005-04-17 02:20:36 +04:00
}
module_init ( init_v2_quota_format ) ;
module_exit ( exit_v2_quota_format ) ;