@ -343,6 +343,24 @@ void d_drop(struct dentry *dentry)
}
EXPORT_SYMBOL ( d_drop ) ;
/*
* d_clear_need_lookup - drop a dentry from cache and clear the need lookup flag
* @ dentry : dentry to drop
*
* This is called when we do a lookup on a placeholder dentry that needed to be
* looked up . The dentry should have been hashed in order for it to be found by
* the lookup code , but now needs to be unhashed while we do the actual lookup
* and clear the DCACHE_NEED_LOOKUP flag .
*/
void d_clear_need_lookup ( struct dentry * dentry )
{
spin_lock ( & dentry - > d_lock ) ;
__d_drop ( dentry ) ;
dentry - > d_flags & = ~ DCACHE_NEED_LOOKUP ;
spin_unlock ( & dentry - > d_lock ) ;
}
EXPORT_SYMBOL ( d_clear_need_lookup ) ;
/*
* Finish off a dentry we ' ve decided to kill .
* dentry - > d_lock must be held , returns with it unlocked .
@ -432,8 +450,13 @@ repeat:
if ( d_unhashed ( dentry ) )
goto kill_it ;
/* Otherwise leave it cached and ensure it's on the LRU */
dentry - > d_flags | = DCACHE_REFERENCED ;
/*
* If this dentry needs lookup , don ' t set the referenced flag so that it
* is more likely to be cleaned up by the dcache shrinker in case of
* memory pressure .
*/
if ( ! d_need_lookup ( dentry ) )
dentry - > d_flags | = DCACHE_REFERENCED ;
dentry_lru_add ( dentry ) ;
dentry - > d_count - - ;
@ -526,10 +549,6 @@ repeat:
*/
rcu_read_lock ( ) ;
ret = dentry - > d_parent ;
if ( ! ret ) {
rcu_read_unlock ( ) ;
goto out ;
}
spin_lock ( & ret - > d_lock ) ;
if ( unlikely ( ret ! = dentry - > d_parent ) ) {
spin_unlock ( & ret - > d_lock ) ;
@ -540,7 +559,6 @@ repeat:
BUG_ON ( ! ret - > d_count ) ;
ret - > d_count + + ;
spin_unlock ( & ret - > d_lock ) ;
out :
return ret ;
}
EXPORT_SYMBOL ( dget_parent ) ;
@ -720,13 +738,11 @@ static void shrink_dentry_list(struct list_head *list)
*
* If flags contains DCACHE_REFERENCED reference dentries will not be pruned .
*/
static void __shrink_dcache_sb ( struct super_block * sb , int * count , int flags )
static void __shrink_dcache_sb ( struct super_block * sb , int count , int flags )
{
/* called from prune_dcache() and shrink_dcache_parent() */
struct dentry * dentry ;
LIST_HEAD ( referenced ) ;
LIST_HEAD ( tmp ) ;
int cnt = * count ;
relock :
spin_lock ( & dcache_lru_lock ) ;
@ -754,7 +770,7 @@ relock:
} else {
list_move_tail ( & dentry - > d_lru , & tmp ) ;
spin_unlock ( & dentry - > d_lock ) ;
if ( ! - - cnt )
if ( ! - - cou nt )
break ;
}
cond_resched_lock ( & dcache_lru_lock ) ;
@ -764,83 +780,22 @@ relock:
spin_unlock ( & dcache_lru_lock ) ;
shrink_dentry_list ( & tmp ) ;
* count = cnt ;
}
/**
* prune_dcache - shrink the dcache
* @ count : number of entries to try to free
* prune_dcache_sb - shrink the dcache
* @ nr_to_scan : number of entries to try to free
*
* Shrink the dcache . This is done when we need more memory , or simply when we
* need to unmount something ( at which point we need to unuse all dentries ) .
* Attempt to shrink the superblock dcache LRU by @ nr_to_scan entries . This is
* done when we need more memory an called from the superblock shrinker
* function .
*
* This function may fail to free any resources if all the dentries are in use .
* This function may fail to free any resources if all the dentries are in
* use .
*/
static void prune_dcache ( int count )
void prune_dcache_sb ( struct super_block * sb , int nr_to_scan )
{
struct super_block * sb , * p = NULL ;
int w_count ;
int unused = dentry_stat . nr_unused ;
int prune_ratio ;
int pruned ;
if ( unused = = 0 | | count = = 0 )
return ;
if ( count > = unused )
prune_ratio = 1 ;
else
prune_ratio = unused / count ;
spin_lock ( & sb_lock ) ;
list_for_each_entry ( sb , & super_blocks , s_list ) {
if ( list_empty ( & sb - > s_instances ) )
continue ;
if ( sb - > s_nr_dentry_unused = = 0 )
continue ;
sb - > s_count + + ;
/* Now, we reclaim unused dentrins with fairness.
* We reclaim them same percentage from each superblock .
* We calculate number of dentries to scan on this sb
* as follows , but the implementation is arranged to avoid
* overflows :
* number of dentries to scan on this sb =
* count * ( number of dentries on this sb /
* number of dentries in the machine )
*/
spin_unlock ( & sb_lock ) ;
if ( prune_ratio ! = 1 )
w_count = ( sb - > s_nr_dentry_unused / prune_ratio ) + 1 ;
else
w_count = sb - > s_nr_dentry_unused ;
pruned = w_count ;
/*
* We need to be sure this filesystem isn ' t being unmounted ,
* otherwise we could race with generic_shutdown_super ( ) , and
* end up holding a reference to an inode while the filesystem
* is unmounted . So we try to get s_umount , and make sure
* s_root isn ' t NULL .
*/
if ( down_read_trylock ( & sb - > s_umount ) ) {
if ( ( sb - > s_root ! = NULL ) & &
( ! list_empty ( & sb - > s_dentry_lru ) ) ) {
__shrink_dcache_sb ( sb , & w_count ,
DCACHE_REFERENCED ) ;
pruned - = w_count ;
}
up_read ( & sb - > s_umount ) ;
}
spin_lock ( & sb_lock ) ;
if ( p )
__put_super ( p ) ;
count - = pruned ;
p = sb ;
/* more work left to do? */
if ( count < = 0 )
break ;
}
if ( p )
__put_super ( p ) ;
spin_unlock ( & sb_lock ) ;
__shrink_dcache_sb ( sb , nr_to_scan , DCACHE_REFERENCED ) ;
}
/**
@ -1215,45 +1170,13 @@ void shrink_dcache_parent(struct dentry * parent)
int found ;
while ( ( found = select_parent ( parent ) ) ! = 0 )
__shrink_dcache_sb ( sb , & found , 0 ) ;
__shrink_dcache_sb ( sb , found , 0 ) ;
}
EXPORT_SYMBOL ( shrink_dcache_parent ) ;
/*
* Scan ` sc - > nr_slab_to_reclaim ' dentries and return the number which remain .
*
* We need to avoid reentering the filesystem if the caller is performing a
* GFP_NOFS allocation attempt . One example deadlock is :
*
* ext2_new_block - > getblk - > GFP - > shrink_dcache_memory - > prune_dcache - >
* prune_one_dentry - > dput - > dentry_iput - > iput - > inode - > i_sb - > s_op - > put_inode - >
* ext2_discard_prealloc - > ext2_free_blocks - > lock_super - > DEADLOCK .
*
* In this case we return - 1 to tell the caller that we baled .
*/
static int shrink_dcache_memory ( struct shrinker * shrink ,
struct shrink_control * sc )
{
int nr = sc - > nr_to_scan ;
gfp_t gfp_mask = sc - > gfp_mask ;
if ( nr ) {
if ( ! ( gfp_mask & __GFP_FS ) )
return - 1 ;
prune_dcache ( nr ) ;
}
return ( dentry_stat . nr_unused / 100 ) * sysctl_vfs_cache_pressure ;
}
static struct shrinker dcache_shrinker = {
. shrink = shrink_dcache_memory ,
. seeks = DEFAULT_SEEKS ,
} ;
/**
* d_alloc - allocate a dcache entry
* @ parent : parent of entry to allocate
* __d_alloc - allocate a dcache entry
* @ sb : filesystem it will belong to
* @ name : qstr of the name
*
* Allocates a dentry . It returns % NULL if there is insufficient memory
@ -1261,7 +1184,7 @@ static struct shrinker dcache_shrinker = {
* copied and the copy passed in may be reused after this call .
*/
struct dentry * d_alloc ( struct dentry * parent , const struct qstr * name )
struct dentry * __ d_alloc( struct super_block * sb , const struct qstr * name )
{
struct dentry * dentry ;
char * dname ;
@ -1291,8 +1214,8 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
spin_lock_init ( & dentry - > d_lock ) ;
seqcount_init ( & dentry - > d_seq ) ;
dentry - > d_inode = NULL ;
dentry - > d_parent = NULL ;
dentry - > d_sb = NULL ;
dentry - > d_parent = dentry ;
dentry - > d_sb = sb ;
dentry - > d_op = NULL ;
dentry - > d_fsdata = NULL ;
INIT_HLIST_BL_NODE ( & dentry - > d_hash ) ;
@ -1300,36 +1223,47 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
INIT_LIST_HEAD ( & dentry - > d_subdirs ) ;
INIT_LIST_HEAD ( & dentry - > d_alias ) ;
INIT_LIST_HEAD ( & dentry - > d_u . d_child ) ;
if ( parent ) {
spin_lock ( & parent - > d_lock ) ;
/*
* don ' t need child lock because it is not subject
* to concurrency here
*/
__dget_dlock ( parent ) ;
dentry - > d_parent = parent ;
dentry - > d_sb = parent - > d_sb ;
d_set_d_op ( dentry , dentry - > d_sb - > s_d_op ) ;
list_add ( & dentry - > d_u . d_child , & parent - > d_subdirs ) ;
spin_unlock ( & parent - > d_lock ) ;
}
d_set_d_op ( dentry , dentry - > d_sb - > s_d_op ) ;
this_cpu_inc ( nr_dentry ) ;
return dentry ;
}
/**
* d_alloc - allocate a dcache entry
* @ parent : parent of entry to allocate
* @ name : qstr of the name
*
* Allocates a dentry . It returns % NULL if there is insufficient memory
* available . On a success the dentry is returned . The name passed in is
* copied and the copy passed in may be reused after this call .
*/
struct dentry * d_alloc ( struct dentry * parent , const struct qstr * name )
{
struct dentry * dentry = __d_alloc ( parent - > d_sb , name ) ;
if ( ! dentry )
return NULL ;
spin_lock ( & parent - > d_lock ) ;
/*
* don ' t need child lock because it is not subject
* to concurrency here
*/
__dget_dlock ( parent ) ;
dentry - > d_parent = parent ;
list_add ( & dentry - > d_u . d_child , & parent - > d_subdirs ) ;
spin_unlock ( & parent - > d_lock ) ;
return dentry ;
}
EXPORT_SYMBOL ( d_alloc ) ;
struct dentry * d_alloc_pseudo ( struct super_block * sb , const struct qstr * name )
{
struct dentry * dentry = d_alloc ( NULL , name ) ;
if ( dentry ) {
dentry - > d_sb = sb ;
d_set_d_op ( dentry , dentry - > d_sb - > s_d_op ) ;
dentry - > d_parent = dentry ;
struct dentry * dentry = __d_alloc ( sb , name ) ;
if ( dentry )
dentry - > d_flags | = DCACHE_DISCONNECTED ;
}
return dentry ;
}
EXPORT_SYMBOL ( d_alloc_pseudo ) ;
@ -1499,13 +1433,9 @@ struct dentry * d_alloc_root(struct inode * root_inode)
if ( root_inode ) {
static const struct qstr name = { . name = " / " , . len = 1 } ;
res = d_alloc ( NULL , & name ) ;
if ( res ) {
res - > d_sb = root_inode - > i_sb ;
d_set_d_op ( res , res - > d_sb - > s_d_op ) ;
res - > d_parent = res ;
res = __d_alloc ( root_inode - > i_sb , & name ) ;
if ( res )
d_instantiate ( res , root_inode ) ;
}
}
return res ;
}
@ -1566,13 +1496,11 @@ struct dentry *d_obtain_alias(struct inode *inode)
if ( res )
goto out_iput ;
tmp = d_alloc ( NULL , & anonstring ) ;
tmp = __ d_alloc( inode - > i_sb , & anonstring ) ;
if ( ! tmp ) {
res = ERR_PTR ( - ENOMEM ) ;
goto out_iput ;
}
tmp - > d_parent = tmp ; /* make sure dput doesn't croak */
spin_lock ( & inode - > i_lock ) ;
res = __d_find_any_alias ( inode ) ;
@ -1584,8 +1512,6 @@ struct dentry *d_obtain_alias(struct inode *inode)
/* attach a disconnected dentry */
spin_lock ( & tmp - > d_lock ) ;
tmp - > d_sb = inode - > i_sb ;
d_set_d_op ( tmp , tmp - > d_sb - > s_d_op ) ;
tmp - > d_inode = inode ;
tmp - > d_flags | = DCACHE_DISCONNECTED ;
list_add ( & tmp - > d_alias , & inode - > i_dentry ) ;
@ -1626,6 +1552,9 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
{
struct dentry * new = NULL ;
if ( IS_ERR ( inode ) )
return ERR_CAST ( inode ) ;
if ( inode & & S_ISDIR ( inode - > i_mode ) ) {
spin_lock ( & inode - > i_lock ) ;
new = __d_find_alias ( inode , 1 ) ;
@ -1708,29 +1637,22 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
}
/*
* Negative dentry : instantiate it unless the inode is a directory and
* already has a dentry .
* We are going to instantiate this dentry , unhash it and clear the
* lookup flag so we can do that .
*/
spin_lock ( & inode - > i_lock ) ;
if ( ! S_ISDIR ( inode - > i_mode ) | | list_empty ( & inode - > i_dentry ) ) {
__d_instantiate ( found , inode ) ;
spin_unlock ( & inode - > i_lock ) ;
security_d_instantiate ( found , inode ) ;
return found ;
}
if ( unlikely ( d_need_lookup ( found ) ) )
d_clear_need_lookup ( found ) ;
/*
* In case a directory already has a ( disconnected ) entry grab a
* reference to it , move it in place and use it .
* Negative dentry : instantiate it unless the inode is a directory and
* already has a dentry .
*/
new = list_entry ( inode - > i_dentry . next , struct dentry , d_alias ) ;
__dget ( new ) ;
spin_unlock ( & inode - > i_lock ) ;
security_d_instantiate ( found , inode ) ;
d_move ( new , found ) ;
iput ( inode ) ;
dput ( found ) ;
return new ;
new = d_splice_alias ( inode , found ) ;
if ( new ) {
dput ( found ) ;
found = new ;
}
return found ;
err_out :
iput ( inode ) ;
@ -3045,8 +2967,6 @@ static void __init dcache_init(void)
*/
dentry_cache = KMEM_CACHE ( dentry ,
SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | SLAB_MEM_SPREAD ) ;
register_shrinker ( & dcache_shrinker ) ;
/* Hash may have been set up in dcache_init_early */
if ( ! hashdist )