@ -34,6 +34,7 @@
# include <linux/percpu.h>
# include <linux/list_sort.h>
# include <linux/lockref.h>
# include <linux/rhashtable.h>
# include "gfs2.h"
# include "incore.h"
@ -50,9 +51,8 @@
# include "trace_gfs2.h"
struct gfs2_glock_iter {
int hash ; /* hash bucket index */
unsigned nhash ; /* Index within current bucket */
struct gfs2_sbd * sdp ; /* incore superblock */
struct rhashtable_iter hti ; /* rhashtable iterator */
struct gfs2_glock * gl ; /* current glock struct */
loff_t last_pos ; /* last position */
} ;
@ -70,44 +70,19 @@ static DEFINE_SPINLOCK(lru_lock);
# define GFS2_GL_HASH_SHIFT 15
# define GFS2_GL_HASH_SIZE (1 << GFS2_GL_HASH_SHIFT)
# define GFS2_GL_HASH_MASK (GFS2_GL_HASH_SIZE - 1)
static struct hlist_bl_head gl_hash_table [ GFS2_GL_HASH_SIZE ] ;
static struct dentry * gfs2_root ;
/**
* gl_hash ( ) - Turn glock number into hash bucket number
* @ lock : The glock number
*
* Returns : The number of the corresponding hash bucket
*/
static unsigned int gl_hash ( const struct gfs2_sbd * sdp ,
const struct lm_lockname * name )
{
unsigned int h ;
h = jhash ( & name - > ln_number , sizeof ( u64 ) , 0 ) ;
h = jhash ( & name - > ln_type , sizeof ( unsigned int ) , h ) ;
h = jhash ( & sdp , sizeof ( struct gfs2_sbd * ) , h ) ;
h & = GFS2_GL_HASH_MASK ;
return h ;
}
static inline void spin_lock_bucket ( unsigned int hash )
{
hlist_bl_lock ( & gl_hash_table [ hash ] ) ;
}
static struct rhashtable_params ht_parms = {
. nelem_hint = GFS2_GL_HASH_SIZE * 3 / 4 ,
. key_len = sizeof ( struct lm_lockname ) ,
. key_offset = offsetof ( struct gfs2_glock , gl_name ) ,
. head_offset = offsetof ( struct gfs2_glock , gl_node ) ,
} ;
static inline void spin_unlock_bucket ( unsigned int hash )
{
hlist_bl_unlock ( & gl_hash_table [ hash ] ) ;
}
static struct rhashtable gl_hash_table ;
static void gfs2_glock_dealloc ( struct rcu_head * rcu )
void gfs2_glock_free ( struct gfs2_glock * gl )
{
struct gfs2_glock * gl = container_of ( rcu , struct gfs2_glock , gl_rcu ) ;
struct gfs2_sbd * sdp = gl - > gl_name . ln_sbd ;
if ( gl - > gl_ops - > go_flags & GLOF_ASPACE ) {
kmem_cache_free ( gfs2_glock_aspace_cachep , gl ) ;
@ -115,13 +90,6 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)
kfree ( gl - > gl_lksb . sb_lvbptr ) ;
kmem_cache_free ( gfs2_glock_cachep , gl ) ;
}
}
void gfs2_glock_free ( struct gfs2_glock * gl )
{
struct gfs2_sbd * sdp = gl - > gl_sbd ;
call_rcu ( & gl - > gl_rcu , gfs2_glock_dealloc ) ;
if ( atomic_dec_and_test ( & sdp - > sd_glock_disposal ) )
wake_up ( & sdp - > sd_glock_wait ) ;
}
@ -192,7 +160,7 @@ static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl)
void gfs2_glock_put ( struct gfs2_glock * gl )
{
struct gfs2_sbd * sdp = gl - > gl_sbd ;
struct gfs2_sbd * sdp = gl - > gl_name . ln_ sbd ;
struct address_space * mapping = gfs2_glock2aspace ( gl ) ;
if ( lockref_put_or_lock ( & gl - > gl_lockref ) )
@ -202,42 +170,13 @@ void gfs2_glock_put(struct gfs2_glock *gl)
gfs2_glock_remove_from_lru ( gl ) ;
spin_unlock ( & gl - > gl_lockref . lock ) ;
spin_lock_bucket ( gl - > gl_hash ) ;
hlist_bl_del_rcu ( & gl - > gl_list ) ;
spin_unlock_bucket ( gl - > gl_hash ) ;
rhashtable_remove_fast ( & gl_hash_table , & gl - > gl_node , ht_parms ) ;
GLOCK_BUG_ON ( gl , ! list_empty ( & gl - > gl_holders ) ) ;
GLOCK_BUG_ON ( gl , mapping & & mapping - > nrpages ) ;
trace_gfs2_glock_put ( gl ) ;
sdp - > sd_lockstruct . ls_ops - > lm_put_lock ( gl ) ;
}
/**
* search_bucket ( ) - Find struct gfs2_glock by lock number
* @ bucket : the bucket to search
* @ name : The lock name
*
* Returns : NULL , or the struct gfs2_glock with the requested number
*/
static struct gfs2_glock * search_bucket ( unsigned int hash ,
const struct gfs2_sbd * sdp ,
const struct lm_lockname * name )
{
struct gfs2_glock * gl ;
struct hlist_bl_node * h ;
hlist_bl_for_each_entry_rcu ( gl , h , & gl_hash_table [ hash ] , gl_list ) {
if ( ! lm_name_equal ( & gl - > gl_name , name ) )
continue ;
if ( gl - > gl_sbd ! = sdp )
continue ;
if ( lockref_get_not_dead ( & gl - > gl_lockref ) )
return gl ;
}
return NULL ;
}
/**
* may_grant - check if its ok to grant a new lock
* @ gl : The glock
@ -506,7 +445,7 @@ __releases(&gl->gl_spin)
__acquires ( & gl - > gl_spin )
{
const struct gfs2_glock_operations * glops = gl - > gl_ops ;
struct gfs2_sbd * sdp = gl - > gl_sbd ;
struct gfs2_sbd * sdp = gl - > gl_name . ln_ sbd ;
unsigned int lck_flags = gh ? gh - > gh_flags : 0 ;
int ret ;
@ -628,7 +567,7 @@ out_unlock:
static void delete_work_func ( struct work_struct * work )
{
struct gfs2_glock * gl = container_of ( work , struct gfs2_glock , gl_delete ) ;
struct gfs2_sbd * sdp = gl - > gl_sbd ;
struct gfs2_sbd * sdp = gl - > gl_name . ln_ sbd ;
struct gfs2_inode * ip ;
struct inode * inode ;
u64 no_addr = gl - > gl_name . ln_number ;
@ -704,15 +643,17 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
struct gfs2_glock * * glp )
{
struct super_block * s = sdp - > sd_vfs ;
struct lm_lockname name = { . ln_number = number , . ln_type = glops - > go_type } ;
struct gfs2_glock * gl , * tmp ;
unsigned int hash = gl_hash ( sdp , & name ) ;
struct lm_lockname name = { . ln_number = number ,
. ln_type = glops - > go_type ,
. ln_sbd = sdp } ;
struct gfs2_glock * gl , * tmp = NULL ;
struct address_space * mapping ;
struct kmem_cache * cachep ;
int ret , tries = 0 ;
rcu_read_lock ( ) ;
gl = search_bucket ( hash , sdp , & name ) ;
rcu_read_unlock ( ) ;
gl = rhashtable_lookup_fast ( & gl_hash_table , & name , ht_parms ) ;
if ( gl & & ! lockref_get_not_dead ( & gl - > gl_lockref ) )
gl = NULL ;
* glp = gl ;
if ( gl )
@ -739,14 +680,13 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
}
atomic_inc ( & sdp - > sd_glock_disposal ) ;
gl - > gl_sbd = sdp ;
gl - > gl_node . next = NULL ;
gl - > gl_flags = 0 ;
gl - > gl_name = name ;
gl - > gl_lockref . count = 1 ;
gl - > gl_state = LM_ST_UNLOCKED ;
gl - > gl_target = LM_ST_UNLOCKED ;
gl - > gl_demote_state = LM_ST_EXCLUSIVE ;
gl - > gl_hash = hash ;
gl - > gl_ops = glops ;
gl - > gl_dstamp = ktime_set ( 0 , 0 ) ;
preempt_disable ( ) ;
@ -771,22 +711,34 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
mapping - > writeback_index = 0 ;
}
spin_lock_bucket ( hash ) ;
tmp = search_bucket ( hash , sdp , & name ) ;
if ( tmp ) {
spin_unlock_bucket ( hash ) ;
kfree ( gl - > gl_lksb . sb_lvbptr ) ;
kmem_cache_free ( cachep , gl ) ;
atomic_dec ( & sdp - > sd_glock_disposal ) ;
gl = tmp ;
} else {
hlist_bl_add_head_rcu ( & gl - > gl_list , & gl_hash_table [ hash ] ) ;
spin_unlock_bucket ( hash ) ;
again :
ret = rhashtable_lookup_insert_fast ( & gl_hash_table , & gl - > gl_node ,
ht_parms ) ;
if ( ret = = 0 ) {
* glp = gl ;
return 0 ;
}
* glp = gl ;
if ( ret = = - EEXIST ) {
ret = 0 ;
tmp = rhashtable_lookup_fast ( & gl_hash_table , & name , ht_parms ) ;
if ( tmp = = NULL | | ! lockref_get_not_dead ( & tmp - > gl_lockref ) ) {
if ( + + tries < 100 ) {
cond_resched ( ) ;
goto again ;
}
tmp = NULL ;
ret = - ENOMEM ;
}
} else {
WARN_ON_ONCE ( ret ) ;
}
kfree ( gl - > gl_lksb . sb_lvbptr ) ;
kmem_cache_free ( cachep , gl ) ;
atomic_dec ( & sdp - > sd_glock_disposal ) ;
* glp = tmp ;
return 0 ;
return ret ;
}
/**
@ -928,7 +880,7 @@ __releases(&gl->gl_spin)
__acquires ( & gl - > gl_spin )
{
struct gfs2_glock * gl = gh - > gh_gl ;
struct gfs2_sbd * sdp = gl - > gl_sbd ;
struct gfs2_sbd * sdp = gl - > gl_name . ln_ sbd ;
struct list_head * insert_pt = NULL ;
struct gfs2_holder * gh2 ;
int try_futile = 0 ;
@ -1006,7 +958,7 @@ trap_recursive:
int gfs2_glock_nq ( struct gfs2_holder * gh )
{
struct gfs2_glock * gl = gh - > gh_gl ;
struct gfs2_sbd * sdp = gl - > gl_sbd ;
struct gfs2_sbd * sdp = gl - > gl_name . ln_ sbd ;
int error = 0 ;
if ( unlikely ( test_bit ( SDF_SHUTDOWN , & sdp - > sd_flags ) ) )
@ -1313,7 +1265,7 @@ static int gfs2_should_freeze(const struct gfs2_glock *gl)
void gfs2_glock_complete ( struct gfs2_glock * gl , int ret )
{
struct lm_lockstruct * ls = & gl - > gl_sbd - > sd_lockstruct ;
struct lm_lockstruct * ls = & gl - > gl_name . ln_ sbd - > sd_lockstruct ;
spin_lock ( & gl - > gl_spin ) ;
gl - > gl_reply = ret ;
@ -1462,31 +1414,26 @@ static struct shrinker glock_shrinker = {
*
*/
static void examine_bucket ( glock_examiner examiner , const struct gfs2_sbd * sdp ,
unsigned int hash )
static void glock_hash_walk ( glock_examiner examiner , const struct gfs2_sbd * sdp )
{
struct gfs2_glock * gl ;
struct hlist_bl_head * head = & gl_hash_table [ hash ] ;
struct hlist_bl_node * pos ;
struct rhash_head * pos , * next ;
const struct bucket_table * tbl ;
int i ;
rcu_read_lock ( ) ;
hlist_bl_for_each_entry_rcu ( gl , pos , head , gl_list ) {
if ( ( gl - > gl_sbd = = sdp ) & & lockref_get_not_dead ( & gl - > gl_lockref ) )
examiner ( gl ) ;
tbl = rht_dereference_rcu ( gl_hash_table . tbl , & gl_hash_table ) ;
for ( i = 0 ; i < tbl - > size ; i + + ) {
rht_for_each_entry_safe ( gl , pos , next , tbl , i , gl_node ) {
if ( ( gl - > gl_name . ln_sbd = = sdp ) & &
lockref_get_not_dead ( & gl - > gl_lockref ) )
examiner ( gl ) ;
}
}
rcu_read_unlock ( ) ;
cond_resched ( ) ;
}
static void glock_hash_walk ( glock_examiner examiner , const struct gfs2_sbd * sdp )
{
unsigned x ;
for ( x = 0 ; x < GFS2_GL_HASH_SIZE ; x + + )
examine_bucket ( examiner , sdp , x ) ;
}
/**
* thaw_glock - thaw out a glock which has an unprocessed reply waiting
* @ gl : The glock to thaw
@ -1569,7 +1516,7 @@ void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
int ret ;
ret = gfs2_truncatei_resume ( ip ) ;
gfs2_assert_withdraw ( gl - > gl_sbd , ret = = 0 ) ;
gfs2_assert_withdraw ( gl - > gl_name . ln_ sbd , ret = = 0 ) ;
spin_lock ( & gl - > gl_spin ) ;
clear_bit ( GLF_LOCK , & gl - > gl_flags ) ;
@ -1733,17 +1680,17 @@ static int gfs2_glstats_seq_show(struct seq_file *seq, void *iter_ptr)
{
struct gfs2_glock * gl = iter_ptr ;
seq_printf ( seq , " G: n:%u/%llx rtt:%lld/%lld rttb:%lld/%lld irt:%lld/%lld dcnt: %lld qcnt: %lld \n " ,
seq_printf ( seq , " G: n:%u/%llx rtt:%llu/%llu rttb:%llu/%llu irt:%llu/%llu dcnt: %llu qcnt: %llu \n " ,
gl - > gl_name . ln_type ,
( unsigned long long ) gl - > gl_name . ln_number ,
( long long ) gl - > gl_stats . stats [ GFS2_LKS_SRTT ] ,
( long long ) gl - > gl_stats . stats [ GFS2_LKS_SRTTVAR ] ,
( long long ) gl - > gl_stats . stats [ GFS2_LKS_SRTTB ] ,
( long long ) gl - > gl_stats . stats [ GFS2_LKS_SRTTVARB ] ,
( long long ) gl - > gl_stats . stats [ GFS2_LKS_SIRT ] ,
( long long ) gl - > gl_stats . stats [ GFS2_LKS_SIRTVAR ] ,
( long long ) gl - > gl_stats . stats [ GFS2_LKS_DCOUNT ] ,
( long long ) gl - > gl_stats . stats [ GFS2_LKS_QCOUNT ] ) ;
( unsigned long long ) gl - > gl_stats . stats [ GFS2_LKS_SRTT ] ,
( unsigned long long ) gl - > gl_stats . stats [ GFS2_LKS_SRTTVAR ] ,
( unsigned long long ) gl - > gl_stats . stats [ GFS2_LKS_SRTTB ] ,
( unsigned long long ) gl - > gl_stats . stats [ GFS2_LKS_SRTTVARB ] ,
( unsigned long long ) gl - > gl_stats . stats [ GFS2_LKS_SIRT ] ,
( unsigned long long ) gl - > gl_stats . stats [ GFS2_LKS_SIRTVAR ] ,
( unsigned long long ) gl - > gl_stats . stats [ GFS2_LKS_DCOUNT ] ,
( unsigned long long ) gl - > gl_stats . stats [ GFS2_LKS_QCOUNT ] ) ;
return 0 ;
}
@ -1776,11 +1723,10 @@ static const char *gfs2_stype[] = {
static int gfs2_sbstats_seq_show ( struct seq_file * seq , void * iter_ptr )
{
struct gfs2_glock_iter * gi = seq - > private ;
struct gfs2_sbd * sdp = gi - > sdp ;
unsigned index = gi - > hash > > 3 ;
unsigned subindex = gi - > hash & 0x07 ;
s64 value ;
struct gfs2_sbd * sdp = seq - > private ;
loff_t pos = * ( loff_t * ) iter_ptr ;
unsigned index = pos > > 3 ;
unsigned subindex = pos & 0x07 ;
int i ;
if ( index = = 0 & & subindex ! = 0 )
@ -1791,12 +1737,12 @@ static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr)
for_each_possible_cpu ( i ) {
const struct gfs2_pcpu_lkstats * lkstats = per_cpu_ptr ( sdp - > sd_lkstats , i ) ;
if ( index = = 0 ) {
value = i ;
} else {
value = lkstats - > lkstats [ ind ex - 1 ] . stats [ subind ex ] ;
}
seq_printf ( seq , " %15lld " , ( long long ) value ) ;
if ( index = = 0 )
seq_printf ( seq , " %15u " , i ) ;
els e
seq_printf ( seq , " %15llu " , ( unsigned long long ) lkstats - >
lkstats [ index - 1 ] . stats [ subindex ] ) ;
}
seq_putc ( seq , ' \n ' ) ;
return 0 ;
@ -1804,20 +1750,24 @@ static int gfs2_sbstats_seq_show(struct seq_file *seq, void *iter_ptr)
int __init gfs2_glock_init ( void )
{
unsigned i ;
for ( i = 0 ; i < GFS2_GL_HASH_SIZE ; i + + ) {
INIT_HLIST_BL_HEAD ( & gl_hash_table [ i ] ) ;
}
int ret ;
ret = rhashtable_init ( & gl_hash_table , & ht_parms ) ;
if ( ret < 0 )
return ret ;
glock_workqueue = alloc_workqueue ( " glock_workqueue " , WQ_MEM_RECLAIM |
WQ_HIGHPRI | WQ_FREEZABLE , 0 ) ;
if ( ! glock_workqueue )
if ( ! glock_workqueue ) {
rhashtable_destroy ( & gl_hash_table ) ;
return - ENOMEM ;
}
gfs2_delete_workqueue = alloc_workqueue ( " delete_workqueue " ,
WQ_MEM_RECLAIM | WQ_FREEZABLE ,
0 ) ;
if ( ! gfs2_delete_workqueue ) {
destroy_workqueue ( glock_workqueue ) ;
rhashtable_destroy ( & gl_hash_table ) ;
return - ENOMEM ;
}
@ -1829,72 +1779,41 @@ int __init gfs2_glock_init(void)
void gfs2_glock_exit ( void )
{
unregister_shrinker ( & glock_shrinker ) ;
rhashtable_destroy ( & gl_hash_table ) ;
destroy_workqueue ( glock_workqueue ) ;
destroy_workqueue ( gfs2_delete_workqueue ) ;
}
static inline struct gfs2_glock * glock_hash_chain ( unsigned hash )
static void gfs2_glock_iter_next ( struct gfs2_glock_iter * gi )
{
return hlist_bl_entry ( hlist_bl_first_rcu ( & gl_hash_table [ hash ] ) ,
struct gfs2_glock , gl_list ) ;
}
static inline struct gfs2_glock * glock_hash_next ( struct gfs2_glock * gl )
{
return hlist_bl_entry ( rcu_dereference ( gl - > gl_list . next ) ,
struct gfs2_glock , gl_list ) ;
}
static int gfs2_glock_iter_next ( struct gfs2_glock_iter * gi )
{
struct gfs2_glock * gl ;
do {
gl = gi - > gl ;
if ( gl ) {
gi - > gl = glock_hash_next ( gl ) ;
gi - > nhash + + ;
} else {
if ( gi - > hash > = GFS2_GL_HASH_SIZE ) {
rcu_read_unlock ( ) ;
return 1 ;
}
gi - > gl = glock_hash_chain ( gi - > hash ) ;
gi - > nhash = 0 ;
}
while ( gi - > gl = = NULL ) {
gi - > hash + + ;
if ( gi - > hash > = GFS2_GL_HASH_SIZE ) {
rcu_read_unlock ( ) ;
return 1 ;
}
gi - > gl = glock_hash_chain ( gi - > hash ) ;
gi - > nhash = 0 ;
gi - > gl = rhashtable_walk_next ( & gi - > hti ) ;
if ( IS_ERR ( gi - > gl ) ) {
if ( PTR_ERR ( gi - > gl ) = = - EAGAIN )
continue ;
gi - > gl = NULL ;
}
/* Skip entries for other sb and dead entries */
} while ( gi - > sdp ! = gi - > gl - > gl_sbd | |
__lockref_is_dead ( & gi - > gl - > gl_lockref ) ) ;
return 0 ;
} while ( ( gi - > gl ) & & ( ( gi - > sdp ! = gi - > gl - > gl_name . ln_sbd ) | |
__lockref_is_dead ( & gi - > gl - > gl_lockref ) ) ) ;
}
static void * gfs2_glock_seq_start ( struct seq_file * seq , loff_t * pos )
{
struct gfs2_glock_iter * gi = seq - > private ;
loff_t n = * pos ;
int ret ;
if ( gi - > last_pos < = * pos )
n = gi - > nhash + ( * pos - gi - > last_pos ) ;
else
gi - > hash = 0 ;
n = ( * pos - gi - > last_pos ) ;
gi - > nhash = 0 ;
rcu_read_lock ( ) ;
ret = rhashtable_walk_start ( & gi - > hti ) ;
if ( ret )
return NULL ;
do {
if ( gfs2_glock_iter_next ( gi ) )
return NULL ;
} while ( n - - ) ;
gfs2_glock_iter_next ( gi ) ;
} while ( gi - > gl & & n - - ) ;
gi - > last_pos = * pos ;
return gi - > gl ;
@ -1907,9 +1826,7 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
( * pos ) + + ;
gi - > last_pos = * pos ;
if ( gfs2_glock_iter_next ( gi ) )
return NULL ;
gfs2_glock_iter_next ( gi ) ;
return gi - > gl ;
}
@ -1917,9 +1834,8 @@ static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)
{
struct gfs2_glock_iter * gi = seq - > private ;
if ( gi - > gl )
rcu_read_unlock ( ) ;
gi - > gl = NULL ;
rhashtable_walk_stop ( & gi - > hti ) ;
}
static int gfs2_glock_seq_show ( struct seq_file * seq , void * iter_ptr )
@ -1930,26 +1846,19 @@ static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
static void * gfs2_sbstats_seq_start ( struct seq_file * seq , loff_t * pos )
{
struct gfs2_glock_iter * gi = seq - > private ;
gi - > hash = * pos ;
preempt_disable ( ) ;
if ( * pos > = GFS2_NR_SBSTATS )
return NULL ;
preempt_disable ( ) ;
return SEQ_START_TOKEN ;
return pos ;
}
static void * gfs2_sbstats_seq_next ( struct seq_file * seq , void * iter_ptr ,
loff_t * pos )
{
struct gfs2_glock_iter * gi = seq - > private ;
( * pos ) + + ;
gi - > hash + + ;
if ( gi - > hash > = GFS2_NR_SBSTATS ) {
preempt_enable ( ) ;
if ( * pos > = GFS2_NR_SBSTATS )
return NULL ;
}
return SEQ_START_TOKEN ;
return pos ;
}
static void gfs2_sbstats_seq_stop ( struct seq_file * seq , void * iter_ptr )
@ -1987,14 +1896,28 @@ static int gfs2_glocks_open(struct inode *inode, struct file *file)
if ( ret = = 0 ) {
struct seq_file * seq = file - > private_data ;
struct gfs2_glock_iter * gi = seq - > private ;
gi - > sdp = inode - > i_private ;
gi - > last_pos = 0 ;
seq - > buf = kmalloc ( GFS2_SEQ_GOODSIZE , GFP_KERNEL | __GFP_NOWARN ) ;
if ( seq - > buf )
seq - > size = GFS2_SEQ_GOODSIZE ;
gi - > gl = NULL ;
ret = rhashtable_walk_init ( & gl_hash_table , & gi - > hti ) ;
}
return ret ;
}
static int gfs2_glocks_release ( struct inode * inode , struct file * file )
{
struct seq_file * seq = file - > private_data ;
struct gfs2_glock_iter * gi = seq - > private ;
gi - > gl = NULL ;
rhashtable_walk_exit ( & gi - > hti ) ;
return seq_release_private ( inode , file ) ;
}
static int gfs2_glstats_open ( struct inode * inode , struct file * file )
{
int ret = seq_open_private ( file , & gfs2_glstats_seq_ops ,
@ -2003,21 +1926,22 @@ static int gfs2_glstats_open(struct inode *inode, struct file *file)
struct seq_file * seq = file - > private_data ;
struct gfs2_glock_iter * gi = seq - > private ;
gi - > sdp = inode - > i_private ;
gi - > last_pos = 0 ;
seq - > buf = kmalloc ( GFS2_SEQ_GOODSIZE , GFP_KERNEL | __GFP_NOWARN ) ;
if ( seq - > buf )
seq - > size = GFS2_SEQ_GOODSIZE ;
gi - > gl = NULL ;
ret = rhashtable_walk_init ( & gl_hash_table , & gi - > hti ) ;
}
return ret ;
}
static int gfs2_sbstats_open ( struct inode * inode , struct file * file )
{
int ret = seq_open_private ( file , & gfs2_sbstats_seq_ops ,
sizeof ( struct gfs2_glock_iter ) ) ;
int ret = seq_open ( file , & gfs2_sbstats_seq_ops ) ;
if ( ret = = 0 ) {
struct seq_file * seq = file - > private_data ;
struct gfs2_glock_iter * gi = seq - > private ;
gi - > sdp = inode - > i_private ;
seq - > private = inode - > i_private ; /* sdp */
}
return ret ;
}
@ -2027,7 +1951,7 @@ static const struct file_operations gfs2_glocks_fops = {
. open = gfs2_glocks_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = seq_release_privat e,
. release = gfs2_glocks_releas e,
} ;
static const struct file_operations gfs2_glstats_fops = {
@ -2035,7 +1959,7 @@ static const struct file_operations gfs2_glstats_fops = {
. open = gfs2_glstats_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = seq_release_privat e,
. release = gfs2_glocks_releas e,
} ;
static const struct file_operations gfs2_sbstats_fops = {
@ -2043,7 +1967,7 @@ static const struct file_operations gfs2_sbstats_fops = {
. open = gfs2_sbstats_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = seq_release_private ,
. release = seq_release ,
} ;
int gfs2_create_debugfs_file ( struct gfs2_sbd * sdp )