2007-06-12 17:07:21 +04:00
/*
* Copyright ( C ) 2007 Oracle . All rights reserved .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation .
*
* This program 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 this program ; if not , write to the
* Free Software Foundation , Inc . , 59 Temple Place - Suite 330 ,
* Boston , MA 021110 - 1307 , USA .
*/
2007-08-29 23:47:34 +04:00
# include <linux/sched.h>
# include <linux/slab.h>
# include <linux/spinlock.h>
# include <linux/completion.h>
# include <linux/buffer_head.h>
# include <linux/module.h>
# include <linux/kobject.h>
2007-04-05 05:22:22 +04:00
# include "ctree.h"
# include "disk-io.h"
# include "transaction.h"
2007-08-29 23:47:34 +04:00
static ssize_t root_blocks_used_show ( struct btrfs_root * root , char * buf )
{
return snprintf ( buf , PAGE_SIZE , " %llu \n " ,
2007-10-16 00:14:19 +04:00
( unsigned long long ) btrfs_root_used ( & root - > root_item ) ) ;
2007-08-29 23:47:34 +04:00
}
static ssize_t root_block_limit_show ( struct btrfs_root * root , char * buf )
{
return snprintf ( buf , PAGE_SIZE , " %llu \n " ,
2007-10-16 00:14:19 +04:00
( unsigned long long ) btrfs_root_limit ( & root - > root_item ) ) ;
2007-08-29 23:47:34 +04:00
}
static ssize_t super_blocks_used_show ( struct btrfs_fs_info * fs , char * buf )
{
2007-10-16 00:15:53 +04:00
2007-08-29 23:47:34 +04:00
return snprintf ( buf , PAGE_SIZE , " %llu \n " ,
2007-10-16 00:15:53 +04:00
( unsigned long long ) btrfs_super_bytes_used ( & fs - > super_copy ) ) ;
2007-08-29 23:47:34 +04:00
}
static ssize_t super_total_blocks_show ( struct btrfs_fs_info * fs , char * buf )
{
return snprintf ( buf , PAGE_SIZE , " %llu \n " ,
2007-10-16 00:15:53 +04:00
( unsigned long long ) btrfs_super_total_bytes ( & fs - > super_copy ) ) ;
2007-08-29 23:47:34 +04:00
}
static ssize_t super_blocksize_show ( struct btrfs_fs_info * fs , char * buf )
{
return snprintf ( buf , PAGE_SIZE , " %llu \n " ,
2007-10-16 00:14:19 +04:00
( unsigned long long ) btrfs_super_sectorsize ( & fs - > super_copy ) ) ;
2007-08-29 23:47:34 +04:00
}
/* this is for root attrs (subvols/snapshots) */
struct btrfs_root_attr {
struct attribute attr ;
ssize_t ( * show ) ( struct btrfs_root * , char * ) ;
ssize_t ( * store ) ( struct btrfs_root * , const char * , size_t ) ;
} ;
# define ROOT_ATTR(name, mode, show, store) \
2009-01-06 05:25:51 +03:00
static struct btrfs_root_attr btrfs_root_attr_ # # name = __ATTR ( name , mode , \
show , store )
2007-08-29 23:47:34 +04:00
ROOT_ATTR ( blocks_used , 0444 , root_blocks_used_show , NULL ) ;
ROOT_ATTR ( block_limit , 0644 , root_block_limit_show , NULL ) ;
static struct attribute * btrfs_root_attrs [ ] = {
& btrfs_root_attr_blocks_used . attr ,
& btrfs_root_attr_block_limit . attr ,
NULL ,
} ;
/* this is for super attrs (actual full fs) */
struct btrfs_super_attr {
struct attribute attr ;
ssize_t ( * show ) ( struct btrfs_fs_info * , char * ) ;
ssize_t ( * store ) ( struct btrfs_fs_info * , const char * , size_t ) ;
} ;
# define SUPER_ATTR(name, mode, show, store) \
2009-01-06 05:25:51 +03:00
static struct btrfs_super_attr btrfs_super_attr_ # # name = __ATTR ( name , mode , \
show , store )
2007-08-29 23:47:34 +04:00
SUPER_ATTR ( blocks_used , 0444 , super_blocks_used_show , NULL ) ;
SUPER_ATTR ( total_blocks , 0444 , super_total_blocks_show , NULL ) ;
SUPER_ATTR ( blocksize , 0444 , super_blocksize_show , NULL ) ;
static struct attribute * btrfs_super_attrs [ ] = {
& btrfs_super_attr_blocks_used . attr ,
& btrfs_super_attr_total_blocks . attr ,
& btrfs_super_attr_blocksize . attr ,
NULL ,
} ;
static ssize_t btrfs_super_attr_show ( struct kobject * kobj ,
struct attribute * attr , char * buf )
{
struct btrfs_fs_info * fs = container_of ( kobj , struct btrfs_fs_info ,
super_kobj ) ;
struct btrfs_super_attr * a = container_of ( attr ,
struct btrfs_super_attr ,
attr ) ;
return a - > show ? a - > show ( fs , buf ) : 0 ;
}
static ssize_t btrfs_super_attr_store ( struct kobject * kobj ,
struct attribute * attr ,
const char * buf , size_t len )
{
struct btrfs_fs_info * fs = container_of ( kobj , struct btrfs_fs_info ,
super_kobj ) ;
struct btrfs_super_attr * a = container_of ( attr ,
struct btrfs_super_attr ,
attr ) ;
return a - > store ? a - > store ( fs , buf , len ) : 0 ;
}
static ssize_t btrfs_root_attr_show ( struct kobject * kobj ,
struct attribute * attr , char * buf )
{
struct btrfs_root * root = container_of ( kobj , struct btrfs_root ,
root_kobj ) ;
struct btrfs_root_attr * a = container_of ( attr ,
struct btrfs_root_attr ,
attr ) ;
return a - > show ? a - > show ( root , buf ) : 0 ;
}
static ssize_t btrfs_root_attr_store ( struct kobject * kobj ,
struct attribute * attr ,
const char * buf , size_t len )
{
struct btrfs_root * root = container_of ( kobj , struct btrfs_root ,
root_kobj ) ;
struct btrfs_root_attr * a = container_of ( attr ,
struct btrfs_root_attr ,
attr ) ;
return a - > store ? a - > store ( root , buf , len ) : 0 ;
}
static void btrfs_super_release ( struct kobject * kobj )
{
struct btrfs_fs_info * fs = container_of ( kobj , struct btrfs_fs_info ,
super_kobj ) ;
complete ( & fs - > kobj_unregister ) ;
}
static void btrfs_root_release ( struct kobject * kobj )
{
struct btrfs_root * root = container_of ( kobj , struct btrfs_root ,
root_kobj ) ;
complete ( & root - > kobj_unregister ) ;
}
2010-01-19 04:58:23 +03:00
static const struct sysfs_ops btrfs_super_attr_ops = {
2007-08-29 23:47:34 +04:00
. show = btrfs_super_attr_show ,
. store = btrfs_super_attr_store ,
} ;
2010-01-19 04:58:23 +03:00
static const struct sysfs_ops btrfs_root_attr_ops = {
2007-08-29 23:47:34 +04:00
. show = btrfs_root_attr_show ,
. store = btrfs_root_attr_store ,
} ;
static struct kobj_type btrfs_root_ktype = {
. default_attrs = btrfs_root_attrs ,
. sysfs_ops = & btrfs_root_attr_ops ,
. release = btrfs_root_release ,
} ;
static struct kobj_type btrfs_super_ktype = {
. default_attrs = btrfs_super_attrs ,
. sysfs_ops = & btrfs_super_attr_ops ,
. release = btrfs_super_release ,
} ;
2008-02-20 22:14:16 +03:00
/* /sys/fs/btrfs/ entry */
static struct kset * btrfs_kset ;
2007-08-29 23:47:34 +04:00
int btrfs_sysfs_add_super ( struct btrfs_fs_info * fs )
{
int error ;
2007-12-19 00:15:09 +03:00
char * name ;
char c ;
int len = strlen ( fs - > sb - > s_id ) + 1 ;
int i ;
name = kmalloc ( len , GFP_NOFS ) ;
if ( ! name ) {
error = - ENOMEM ;
goto fail ;
}
for ( i = 0 ; i < len ; i + + ) {
c = fs - > sb - > s_id [ i ] ;
if ( c = = ' / ' | | c = = ' \\ ' )
c = ' ! ' ;
name [ i ] = c ;
}
name [ len ] = ' \0 ' ;
2007-08-29 23:47:34 +04:00
2008-02-20 22:14:16 +03:00
fs - > super_kobj . kset = btrfs_kset ;
error = kobject_init_and_add ( & fs - > super_kobj , & btrfs_super_ktype ,
NULL , " %s " , name ) ;
2009-01-05 23:43:42 +03:00
kfree ( name ) ;
2007-08-29 23:47:34 +04:00
if ( error )
goto fail ;
return 0 ;
fail :
printk ( KERN_ERR " btrfs: sysfs creation for super failed \n " ) ;
return error ;
}
int btrfs_sysfs_add_root ( struct btrfs_root * root )
{
int error ;
2008-02-20 22:14:16 +03:00
error = kobject_init_and_add ( & root - > root_kobj , & btrfs_root_ktype ,
& root - > fs_info - > super_kobj ,
" %s " , root - > name ) ;
2007-08-29 23:47:34 +04:00
if ( error )
goto fail ;
return 0 ;
fail :
printk ( KERN_ERR " btrfs: sysfs creation for root failed \n " ) ;
return error ;
}
void btrfs_sysfs_del_root ( struct btrfs_root * root )
{
2008-02-20 22:14:16 +03:00
kobject_put ( & root - > root_kobj ) ;
2007-08-29 23:47:34 +04:00
wait_for_completion ( & root - > kobj_unregister ) ;
}
void btrfs_sysfs_del_super ( struct btrfs_fs_info * fs )
{
2008-02-20 22:14:16 +03:00
kobject_put ( & fs - > super_kobj ) ;
2007-08-29 23:47:34 +04:00
wait_for_completion ( & fs - > kobj_unregister ) ;
}
2008-09-06 00:43:31 +04:00
int btrfs_init_sysfs ( void )
2007-08-29 23:47:34 +04:00
{
2008-02-20 22:14:16 +03:00
btrfs_kset = kset_create_and_add ( " btrfs " , NULL , fs_kobj ) ;
if ( ! btrfs_kset )
return - ENOMEM ;
return 0 ;
2007-08-29 23:47:34 +04:00
}
2008-09-06 00:43:31 +04:00
void btrfs_exit_sysfs ( void )
2007-08-29 23:47:34 +04:00
{
2008-02-20 22:14:16 +03:00
kset_unregister ( btrfs_kset ) ;
2007-08-29 23:47:34 +04:00
}
2008-02-21 00:02:51 +03:00