2007-04-27 02:49:28 +04:00
/* AFS superblock handling
*
2007-04-27 02:55:03 +04:00
* Copyright ( c ) 2002 , 2007 Red Hat , Inc . All rights reserved .
2005-04-17 02:20:36 +04:00
*
* This software may be freely redistributed under the terms of the
* GNU General Public License .
*
* 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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
* Authors : David Howells < dhowells @ redhat . com >
2008-06-06 09:46:18 +04:00
* David Woodhouse < dwmw2 @ infradead . org >
2005-04-17 02:20:36 +04:00
*
*/
# include <linux/kernel.h>
# include <linux/module.h>
2010-08-11 12:38:04 +04:00
# include <linux/mount.h>
2005-04-17 02:20:36 +04:00
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/fs.h>
# include <linux/pagemap.h>
2007-05-03 14:11:29 +04:00
# include <linux/parser.h>
2007-05-11 09:22:20 +04:00
# include <linux/statfs.h>
Detach sched.h from mm.h
First thing mm.h does is including sched.h solely for can_do_mlock() inline
function which has "current" dereference inside. By dealing with can_do_mlock()
mm.h can be detached from sched.h which is good. See below, why.
This patch
a) removes unconditional inclusion of sched.h from mm.h
b) makes can_do_mlock() normal function in mm/mlock.c
c) exports can_do_mlock() to not break compilation
d) adds sched.h inclusions back to files that were getting it indirectly.
e) adds less bloated headers to some files (asm/signal.h, jiffies.h) that were
getting them indirectly
Net result is:
a) mm.h users would get less code to open, read, preprocess, parse, ... if
they don't need sched.h
b) sched.h stops being dependency for significant number of files:
on x86_64 allmodconfig touching sched.h results in recompile of 4083 files,
after patch it's only 3744 (-8.3%).
Cross-compile tested on
all arm defconfigs, all mips defconfigs, all powerpc defconfigs,
alpha alpha-up
arm
i386 i386-up i386-defconfig i386-allnoconfig
ia64 ia64-up
m68k
mips
parisc parisc-up
powerpc powerpc-up
s390 s390-up
sparc sparc-up
sparc64 sparc64-up
um-x86_64
x86_64 x86_64-up x86_64-defconfig x86_64-allnoconfig
as well as my two usual configs.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-05-21 01:22:52 +04:00
# include <linux/sched.h>
2013-01-31 16:23:54 +04:00
# include <linux/nsproxy.h>
# include <net/net_namespace.h>
2005-04-17 02:20:36 +04:00
# include "internal.h"
# define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
2008-07-26 06:45:34 +04:00
static void afs_i_init_once ( void * foo ) ;
2010-07-26 14:16:21 +04:00
static struct dentry * afs_mount ( struct file_system_type * fs_type ,
int flags , const char * dev_name , void * data ) ;
2011-06-13 00:01:21 +04:00
static void afs_kill_super ( struct super_block * sb ) ;
2005-04-17 02:20:36 +04:00
static struct inode * afs_alloc_inode ( struct super_block * sb ) ;
static void afs_destroy_inode ( struct inode * inode ) ;
2007-05-11 09:22:20 +04:00
static int afs_statfs ( struct dentry * dentry , struct kstatfs * buf ) ;
2005-04-17 02:20:36 +04:00
2006-06-09 17:34:16 +04:00
struct file_system_type afs_fs_type = {
2005-04-17 02:20:36 +04:00
. owner = THIS_MODULE ,
. name = " afs " ,
2010-07-26 14:16:21 +04:00
. mount = afs_mount ,
2011-06-13 00:01:21 +04:00
. kill_sb = afs_kill_super ,
2007-05-03 14:11:29 +04:00
. fs_flags = 0 ,
2005-04-17 02:20:36 +04:00
} ;
2013-03-03 07:39:14 +04:00
MODULE_ALIAS_FS ( " afs " ) ;
2005-04-17 02:20:36 +04:00
2007-02-12 11:55:41 +03:00
static const struct super_operations afs_super_ops = {
2007-05-11 09:22:20 +04:00
. statfs = afs_statfs ,
2005-04-17 02:20:36 +04:00
. alloc_inode = afs_alloc_inode ,
2010-08-11 12:38:04 +04:00
. drop_inode = afs_drop_inode ,
2005-04-17 02:20:36 +04:00
. destroy_inode = afs_destroy_inode ,
2010-06-07 22:34:48 +04:00
. evict_inode = afs_evict_inode ,
2008-02-08 15:21:37 +03:00
. show_options = generic_show_options ,
2005-04-17 02:20:36 +04:00
} ;
2006-12-07 07:33:20 +03:00
static struct kmem_cache * afs_inode_cachep ;
2005-04-17 02:20:36 +04:00
static atomic_t afs_count_active_inodes ;
2007-05-03 14:11:29 +04:00
enum {
afs_no_opt ,
afs_opt_cell ,
afs_opt_rwpath ,
afs_opt_vol ,
2010-08-11 12:38:04 +04:00
afs_opt_autocell ,
2007-05-03 14:11:29 +04:00
} ;
2008-10-13 13:46:57 +04:00
static const match_table_t afs_options_list = {
2007-05-03 14:11:29 +04:00
{ afs_opt_cell , " cell=%s " } ,
{ afs_opt_rwpath , " rwpath " } ,
{ afs_opt_vol , " vol=%s " } ,
2010-08-11 12:38:04 +04:00
{ afs_opt_autocell , " autocell " } ,
2007-05-03 14:11:29 +04:00
{ afs_no_opt , NULL } ,
} ;
2005-04-17 02:20:36 +04:00
/*
* initialise the filesystem
*/
int __init afs_fs_init ( void )
{
int ret ;
_enter ( " " ) ;
/* create ourselves an inode cache */
atomic_set ( & afs_count_active_inodes , 0 ) ;
ret = - ENOMEM ;
afs_inode_cachep = kmem_cache_create ( " afs_inode_cache " ,
sizeof ( struct afs_vnode ) ,
0 ,
2016-01-15 02:18:21 +03:00
SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT ,
2007-07-20 05:11:58 +04:00
afs_i_init_once ) ;
2005-04-17 02:20:36 +04:00
if ( ! afs_inode_cachep ) {
printk ( KERN_NOTICE " kAFS: Failed to allocate inode cache \n " ) ;
return ret ;
}
/* now export our filesystem to lesser mortals */
ret = register_filesystem ( & afs_fs_type ) ;
if ( ret < 0 ) {
kmem_cache_destroy ( afs_inode_cachep ) ;
2007-04-27 02:55:03 +04:00
_leave ( " = %d " , ret ) ;
2005-04-17 02:20:36 +04:00
return ret ;
}
2007-04-27 02:55:03 +04:00
_leave ( " = 0 " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* clean up the filesystem
*/
void __exit afs_fs_exit ( void )
{
2007-04-27 02:55:03 +04:00
_enter ( " " ) ;
afs_mntpt_kill_timer ( ) ;
2005-04-17 02:20:36 +04:00
unregister_filesystem ( & afs_fs_type ) ;
if ( atomic_read ( & afs_count_active_inodes ) ! = 0 ) {
printk ( " kAFS: %d active inode objects still present \n " ,
atomic_read ( & afs_count_active_inodes ) ) ;
BUG ( ) ;
}
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 ( afs_inode_cachep ) ;
2007-04-27 02:55:03 +04:00
_leave ( " " ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* parse the mount options
* - this function has been shamelessly adapted from the ext3 fs which
* shamelessly adapted it from the msdos fs
*/
2007-04-27 02:57:07 +04:00
static int afs_parse_options ( struct afs_mount_params * params ,
char * options , const char * * devname )
2005-04-17 02:20:36 +04:00
{
2007-04-27 02:55:03 +04:00
struct afs_cell * cell ;
2007-05-03 14:11:29 +04:00
substring_t args [ MAX_OPT_ARGS ] ;
char * p ;
int token ;
2005-04-17 02:20:36 +04:00
_enter ( " %s " , options ) ;
options [ PAGE_SIZE - 1 ] = 0 ;
2007-05-03 14:11:29 +04:00
while ( ( p = strsep ( & options , " , " ) ) ) {
if ( ! * p )
continue ;
2005-04-17 02:20:36 +04:00
2007-05-03 14:11:29 +04:00
token = match_token ( p , afs_options_list , args ) ;
switch ( token ) {
case afs_opt_cell :
cell = afs_cell_lookup ( args [ 0 ] . from ,
2010-08-11 12:38:04 +04:00
args [ 0 ] . to - args [ 0 ] . from ,
false ) ;
2007-04-27 02:55:03 +04:00
if ( IS_ERR ( cell ) )
return PTR_ERR ( cell ) ;
2007-04-27 02:57:07 +04:00
afs_put_cell ( params - > cell ) ;
params - > cell = cell ;
2007-05-03 14:11:29 +04:00
break ;
case afs_opt_rwpath :
params - > rwpath = 1 ;
break ;
case afs_opt_vol :
* devname = args [ 0 ] . from ;
break ;
2010-08-11 12:38:04 +04:00
case afs_opt_autocell :
params - > autocell = 1 ;
break ;
2007-05-03 14:11:29 +04:00
default :
printk ( KERN_ERR " kAFS: "
" Unknown or invalid mount option: '%s' \n " , p ) ;
return - EINVAL ;
2005-04-17 02:20:36 +04:00
}
}
2007-05-03 14:11:29 +04:00
_leave ( " = 0 " ) ;
return 0 ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
2007-04-27 02:57:07 +04:00
/*
* parse a device name to get cell name , volume name , volume type and R / W
* selector
* - this can be one of the following :
* " %[cell:]volume[.] " R / W volume
* " #[cell:]volume[.] " R / O or R / W volume ( rwpath = 0 ) ,
* or R / W ( rwpath = 1 ) volume
* " %[cell:]volume.readonly " R / O volume
* " #[cell:]volume.readonly " R / O volume
* " %[cell:]volume.backup " Backup volume
* " #[cell:]volume.backup " Backup volume
*/
static int afs_parse_device_name ( struct afs_mount_params * params ,
const char * name )
{
struct afs_cell * cell ;
const char * cellname , * suffix ;
int cellnamesz ;
_enter ( " ,%s " , name ) ;
if ( ! name ) {
printk ( KERN_ERR " kAFS: no volume name specified \n " ) ;
return - EINVAL ;
}
if ( ( name [ 0 ] ! = ' % ' & & name [ 0 ] ! = ' # ' ) | | ! name [ 1 ] ) {
printk ( KERN_ERR " kAFS: unparsable volume name \n " ) ;
return - EINVAL ;
}
/* determine the type of volume we're looking for */
params - > type = AFSVL_ROVOL ;
params - > force = false ;
if ( params - > rwpath | | name [ 0 ] = = ' % ' ) {
params - > type = AFSVL_RWVOL ;
params - > force = true ;
}
name + + ;
/* split the cell name out if there is one */
params - > volname = strchr ( name , ' : ' ) ;
if ( params - > volname ) {
cellname = name ;
cellnamesz = params - > volname - name ;
params - > volname + + ;
} else {
params - > volname = name ;
cellname = NULL ;
cellnamesz = 0 ;
}
/* the volume type is further affected by a possible suffix */
suffix = strrchr ( params - > volname , ' . ' ) ;
if ( suffix ) {
if ( strcmp ( suffix , " .readonly " ) = = 0 ) {
params - > type = AFSVL_ROVOL ;
params - > force = true ;
} else if ( strcmp ( suffix , " .backup " ) = = 0 ) {
params - > type = AFSVL_BACKVOL ;
params - > force = true ;
} else if ( suffix [ 1 ] = = 0 ) {
} else {
suffix = NULL ;
}
}
params - > volnamesz = suffix ?
suffix - params - > volname : strlen ( params - > volname ) ;
_debug ( " cell %*.*s [%p] " ,
cellnamesz , cellnamesz , cellname ? : " " , params - > cell ) ;
/* lookup the cell record */
if ( cellname | | ! params - > cell ) {
2010-08-11 12:38:04 +04:00
cell = afs_cell_lookup ( cellname , cellnamesz , true ) ;
2007-04-27 02:57:07 +04:00
if ( IS_ERR ( cell ) ) {
2010-08-11 12:38:04 +04:00
printk ( KERN_ERR " kAFS: unable to lookup cell '%*.*s' \n " ,
cellnamesz , cellnamesz , cellname ? : " " ) ;
2007-04-27 02:57:07 +04:00
return PTR_ERR ( cell ) ;
}
afs_put_cell ( params - > cell ) ;
params - > cell = cell ;
}
_debug ( " CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s " ,
params - > cell - > name , params - > cell ,
params - > volnamesz , params - > volnamesz , params - > volname ,
suffix ? : " - " , params - > type , params - > force ? " FORCE " : " " ) ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
/*
* check a superblock to see if it ' s the one we ' re looking for
*/
static int afs_test_super ( struct super_block * sb , void * data )
{
2011-06-13 00:01:21 +04:00
struct afs_super_info * as1 = data ;
2005-04-17 02:20:36 +04:00
struct afs_super_info * as = sb - > s_fs_info ;
2011-06-13 00:01:21 +04:00
return as - > volume = = as1 - > volume ;
}
static int afs_set_super ( struct super_block * sb , void * data )
{
sb - > s_fs_info = data ;
return set_anon_super ( sb , NULL ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* fill in the superblock
*/
2011-06-13 00:01:21 +04:00
static int afs_fill_super ( struct super_block * sb ,
struct afs_mount_params * params )
2005-04-17 02:20:36 +04:00
{
2011-06-13 00:01:21 +04:00
struct afs_super_info * as = sb - > s_fs_info ;
2005-04-17 02:20:36 +04:00
struct afs_fid fid ;
struct inode * inode = NULL ;
int ret ;
2007-04-27 02:55:03 +04:00
_enter ( " " ) ;
2005-04-17 02:20:36 +04:00
/* fill in the superblock */
sb - > s_blocksize = PAGE_CACHE_SIZE ;
sb - > s_blocksize_bits = PAGE_CACHE_SHIFT ;
sb - > s_magic = AFS_FS_MAGIC ;
sb - > s_op = & afs_super_ops ;
2010-04-22 13:58:18 +04:00
sb - > s_bdi = & as - > volume - > bdi ;
2011-06-14 03:38:44 +04:00
strlcpy ( sb - > s_id , as - > volume - > vlocation - > vldb . name , sizeof ( sb - > s_id ) ) ;
2005-04-17 02:20:36 +04:00
/* allocate the root inode and dentry */
fid . vid = as - > volume - > vid ;
fid . vnode = 1 ;
fid . unique = 1 ;
2007-04-27 02:59:35 +04:00
inode = afs_iget ( sb , params - > key , & fid , NULL , NULL ) ;
2007-04-27 02:55:03 +04:00
if ( IS_ERR ( inode ) )
2011-06-13 00:01:21 +04:00
return PTR_ERR ( inode ) ;
2005-04-17 02:20:36 +04:00
2010-08-11 12:38:04 +04:00
if ( params - > autocell )
set_bit ( AFS_VNODE_AUTOCELL , & AFS_FS_I ( inode ) - > flags ) ;
2005-04-17 02:20:36 +04:00
ret = - ENOMEM ;
2012-01-09 07:15:13 +04:00
sb - > s_root = d_make_root ( inode ) ;
if ( ! sb - > s_root )
2005-04-17 02:20:36 +04:00
goto error ;
2011-01-13 04:04:20 +03:00
sb - > s_d_op = & afs_fs_dentry_operations ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
_leave ( " = 0 " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2007-04-27 02:49:28 +04:00
error :
2007-04-27 02:55:03 +04:00
_leave ( " = %d " , ret ) ;
2005-04-17 02:20:36 +04:00
return ret ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* get an AFS superblock
*/
2010-07-26 14:16:21 +04:00
static struct dentry * afs_mount ( struct file_system_type * fs_type ,
int flags , const char * dev_name , void * options )
2005-04-17 02:20:36 +04:00
{
struct afs_mount_params params ;
struct super_block * sb ;
2007-04-27 02:55:03 +04:00
struct afs_volume * vol ;
2007-04-27 02:57:07 +04:00
struct key * key ;
2008-02-08 15:21:37 +03:00
char * new_opts = kstrdup ( options , GFP_KERNEL ) ;
2011-06-13 00:01:21 +04:00
struct afs_super_info * as ;
2005-04-17 02:20:36 +04:00
int ret ;
_enter ( " ,,%s,%p " , dev_name , options ) ;
memset ( & params , 0 , sizeof ( params ) ) ;
2013-01-31 16:23:54 +04:00
ret = - EINVAL ;
if ( current - > nsproxy - > net_ns ! = & init_net )
goto error ;
2007-04-27 02:57:07 +04:00
/* parse the options and device name */
2005-04-17 02:20:36 +04:00
if ( options ) {
2007-04-27 02:57:07 +04:00
ret = afs_parse_options ( & params , options , & dev_name ) ;
2005-04-17 02:20:36 +04:00
if ( ret < 0 )
goto error ;
}
2007-04-27 02:57:07 +04:00
ret = afs_parse_device_name ( & params , dev_name ) ;
if ( ret < 0 )
goto error ;
/* try and do the mount securely */
key = afs_request_key ( params . cell ) ;
if ( IS_ERR ( key ) ) {
_leave ( " = %ld [key] " , PTR_ERR ( key ) ) ;
ret = PTR_ERR ( key ) ;
goto error ;
}
params . key = key ;
2005-04-17 02:20:36 +04:00
/* parse the device name */
2007-04-27 02:57:07 +04:00
vol = afs_volume_lookup ( & params ) ;
2007-04-27 02:55:03 +04:00
if ( IS_ERR ( vol ) ) {
ret = PTR_ERR ( vol ) ;
2005-04-17 02:20:36 +04:00
goto error ;
2007-04-27 02:55:03 +04:00
}
2011-06-13 00:01:21 +04:00
/* allocate a superblock info record */
as = kzalloc ( sizeof ( struct afs_super_info ) , GFP_KERNEL ) ;
if ( ! as ) {
ret = - ENOMEM ;
afs_put_volume ( vol ) ;
goto error ;
}
as - > volume = vol ;
2005-04-17 02:20:36 +04:00
/* allocate a deviceless superblock */
2012-06-25 15:55:37 +04:00
sb = sget ( fs_type , afs_test_super , afs_set_super , flags , as ) ;
2007-04-27 02:55:03 +04:00
if ( IS_ERR ( sb ) ) {
ret = PTR_ERR ( sb ) ;
2011-06-13 00:01:21 +04:00
afs_put_volume ( vol ) ;
kfree ( as ) ;
2005-04-17 02:20:36 +04:00
goto error ;
2007-04-27 02:55:03 +04:00
}
2005-04-17 02:20:36 +04:00
2007-04-27 02:56:24 +04:00
if ( ! sb - > s_root ) {
/* initial superblock/root creation */
_debug ( " create " ) ;
ret = afs_fill_super ( sb , & params ) ;
if ( ret < 0 ) {
2009-05-06 09:34:22 +04:00
deactivate_locked_super ( sb ) ;
2007-04-27 02:56:24 +04:00
goto error ;
}
2009-05-09 00:05:57 +04:00
save_mount_options ( sb , new_opts ) ;
2007-04-27 02:56:24 +04:00
sb - > s_flags | = MS_ACTIVE ;
} else {
_debug ( " reuse " ) ;
ASSERTCMP ( sb - > s_flags , & , MS_ACTIVE ) ;
2011-06-13 00:01:21 +04:00
afs_put_volume ( vol ) ;
kfree ( as ) ;
2005-04-17 02:20:36 +04:00
}
2007-04-27 02:57:07 +04:00
afs_put_cell ( params . cell ) ;
2009-05-09 00:05:57 +04:00
kfree ( new_opts ) ;
2007-04-27 02:55:03 +04:00
_leave ( " = 0 [%p] " , sb ) ;
2010-07-26 14:16:21 +04:00
return dget ( sb - > s_root ) ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:49:28 +04:00
error :
2007-04-27 02:57:07 +04:00
afs_put_cell ( params . cell ) ;
key_put ( params . key ) ;
2008-02-08 15:21:37 +03:00
kfree ( new_opts ) ;
2005-04-17 02:20:36 +04:00
_leave ( " = %d " , ret ) ;
2010-07-26 14:16:21 +04:00
return ERR_PTR ( ret ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
2011-06-13 00:01:21 +04:00
static void afs_kill_super ( struct super_block * sb )
2005-04-17 02:20:36 +04:00
{
struct afs_super_info * as = sb - > s_fs_info ;
2011-06-13 00:01:21 +04:00
kill_anon_super ( sb ) ;
2005-04-17 02:20:36 +04:00
afs_put_volume ( as - > volume ) ;
2011-06-13 00:01:21 +04:00
kfree ( as ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* initialise an inode cache slab element prior to any use
*/
2008-07-26 06:45:34 +04:00
static void afs_i_init_once ( void * _vnode )
2005-04-17 02:20:36 +04:00
{
2007-04-27 02:49:28 +04:00
struct afs_vnode * vnode = _vnode ;
2005-04-17 02:20:36 +04:00
2007-05-17 09:10:57 +04:00
memset ( vnode , 0 , sizeof ( * vnode ) ) ;
inode_init_once ( & vnode - > vfs_inode ) ;
init_waitqueue_head ( & vnode - > update_waitq ) ;
mutex_init ( & vnode - > permits_lock ) ;
mutex_init ( & vnode - > validate_lock ) ;
spin_lock_init ( & vnode - > writeback_lock ) ;
spin_lock_init ( & vnode - > lock ) ;
INIT_LIST_HEAD ( & vnode - > writebacks ) ;
2007-07-16 10:40:12 +04:00
INIT_LIST_HEAD ( & vnode - > pending_locks ) ;
INIT_LIST_HEAD ( & vnode - > granted_locks ) ;
INIT_DELAYED_WORK ( & vnode - > lock_work , afs_lock_work ) ;
2007-05-17 09:10:57 +04:00
INIT_WORK ( & vnode - > cb_broken_work , afs_broken_callback_work ) ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
/*
* allocate an AFS inode struct from our slab cache
*/
static struct inode * afs_alloc_inode ( struct super_block * sb )
{
struct afs_vnode * vnode ;
2007-04-27 02:49:28 +04:00
vnode = kmem_cache_alloc ( afs_inode_cachep , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! vnode )
return NULL ;
atomic_inc ( & afs_count_active_inodes ) ;
memset ( & vnode - > fid , 0 , sizeof ( vnode - > fid ) ) ;
memset ( & vnode - > status , 0 , sizeof ( vnode - > status ) ) ;
vnode - > volume = NULL ;
vnode - > update_cnt = 0 ;
2007-04-27 02:59:35 +04:00
vnode - > flags = 1 < < AFS_VNODE_UNSET ;
2007-04-27 02:55:03 +04:00
vnode - > cb_promised = false ;
2005-04-17 02:20:36 +04:00
2007-05-11 09:22:20 +04:00
_leave ( " = %p " , & vnode - > vfs_inode ) ;
2005-04-17 02:20:36 +04:00
return & vnode - > vfs_inode ;
2007-04-27 02:49:28 +04:00
}
2005-04-17 02:20:36 +04:00
2011-01-07 09:49:49 +03:00
static void afs_i_callback ( struct rcu_head * head )
{
struct inode * inode = container_of ( head , struct inode , i_rcu ) ;
struct afs_vnode * vnode = AFS_FS_I ( inode ) ;
kmem_cache_free ( afs_inode_cachep , vnode ) ;
}
2005-04-17 02:20:36 +04:00
/*
* destroy an AFS inode struct
*/
static void afs_destroy_inode ( struct inode * inode )
{
2007-04-27 02:55:03 +04:00
struct afs_vnode * vnode = AFS_FS_I ( inode ) ;
2007-05-11 09:22:20 +04:00
_enter ( " %p{%x:%u} " , inode , vnode - > fid . vid , vnode - > fid . vnode ) ;
2005-04-17 02:20:36 +04:00
2007-04-27 02:55:03 +04:00
_debug ( " DESTROY INODE %p " , inode ) ;
ASSERTCMP ( vnode - > server , = = , NULL ) ;
2011-01-07 09:49:49 +03:00
call_rcu ( & inode - > i_rcu , afs_i_callback ) ;
2005-04-17 02:20:36 +04:00
atomic_dec ( & afs_count_active_inodes ) ;
2007-04-27 02:49:28 +04:00
}
2007-05-11 09:22:20 +04:00
/*
* return information about an AFS volume
*/
static int afs_statfs ( struct dentry * dentry , struct kstatfs * buf )
{
struct afs_volume_status vs ;
2015-03-18 01:25:59 +03:00
struct afs_vnode * vnode = AFS_FS_I ( d_inode ( dentry ) ) ;
2007-05-11 09:22:20 +04:00
struct key * key ;
int ret ;
key = afs_request_key ( vnode - > volume - > cell ) ;
if ( IS_ERR ( key ) )
return PTR_ERR ( key ) ;
ret = afs_vnode_get_volume_status ( vnode , key , & vs ) ;
key_put ( key ) ;
if ( ret < 0 ) {
_leave ( " = %d " , ret ) ;
return ret ;
}
buf - > f_type = dentry - > d_sb - > s_magic ;
buf - > f_bsize = AFS_BLOCK_SIZE ;
buf - > f_namelen = AFSNAMEMAX - 1 ;
if ( vs . max_quota = = 0 )
buf - > f_blocks = vs . part_max_blocks ;
else
buf - > f_blocks = vs . max_quota ;
buf - > f_bavail = buf - > f_bfree = buf - > f_blocks - vs . blocks_in_use ;
return 0 ;
}