Hi Gang, On 19/6/11 09:54, Gang He wrote: > ocfs2 file system uses locking_state file under debugfs to dump > each ocfs2 file system's dlm lock resources, but the users ever > encountered some hang(deadlock) problems in ocfs2 file system. > I'd like to add first lock wait time in locking_state file, which > can help the upper scripts detect these deadlock problems via > comparing the first lock wait time with the current time. > > Signed-off-by: Gang He <g...@suse.com> > --- > fs/ocfs2/dlmglue.c | 32 +++++++++++++++++++++++++++++--- > fs/ocfs2/ocfs2.h | 1 + > 2 files changed, 30 insertions(+), 3 deletions(-) > > diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c > index d4caa6d117c6..8ce4b76f81ee 100644 > --- a/fs/ocfs2/dlmglue.c > +++ b/fs/ocfs2/dlmglue.c > @@ -440,6 +440,7 @@ static void ocfs2_remove_lockres_tracking(struct > ocfs2_lock_res *res) > static void ocfs2_init_lock_stats(struct ocfs2_lock_res *res) > { > res->l_lock_refresh = 0; > + res->l_lock_wait = 0; > memset(&res->l_lock_prmode, 0, sizeof(struct ocfs2_lock_stats)); > memset(&res->l_lock_exmode, 0, sizeof(struct ocfs2_lock_stats)); > } > @@ -483,6 +484,21 @@ static inline void ocfs2_track_lock_refresh(struct > ocfs2_lock_res *lockres) > lockres->l_lock_refresh++; > } > > +static inline void ocfs2_track_lock_wait(struct ocfs2_lock_res *lockres) > +{ > + struct ocfs2_mask_waiter *mw; > + > + if (list_empty(&lockres->l_mask_waiters)) { > + lockres->l_lock_wait = 0; > + return; > + } > + > + mw = list_first_entry(&lockres->l_mask_waiters, > + struct ocfs2_mask_waiter, mw_item); > + lockres->l_lock_wait = > + ktime_to_us(ktime_mono_to_real(mw->mw_lock_start));
I wonder why ktime_mono_to_real() here? Thanks, Joseph > +} > + > static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw) > { > mw->mw_lock_start = ktime_get(); > @@ -498,6 +514,9 @@ static inline void ocfs2_update_lock_stats(struct > ocfs2_lock_res *res, > static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres) > { > } > +static inline void ocfs2_track_lock_wait(struct ocfs2_lock_res *lockres) > +{ > +} > static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw) > { > } > @@ -891,6 +910,7 @@ static void lockres_set_flags(struct ocfs2_lock_res > *lockres, > list_del_init(&mw->mw_item); > mw->mw_status = 0; > complete(&mw->mw_complete); > + ocfs2_track_lock_wait(lockres); > } > } > static void lockres_or_flags(struct ocfs2_lock_res *lockres, unsigned long > or) > @@ -1402,6 +1422,7 @@ static void lockres_add_mask_waiter(struct > ocfs2_lock_res *lockres, > list_add_tail(&mw->mw_item, &lockres->l_mask_waiters); > mw->mw_mask = mask; > mw->mw_goal = goal; > + ocfs2_track_lock_wait(lockres); > } > > /* returns 0 if the mw that was removed was already satisfied, -EBUSY > @@ -1418,6 +1439,7 @@ static int __lockres_remove_mask_waiter(struct > ocfs2_lock_res *lockres, > > list_del_init(&mw->mw_item); > init_completion(&mw->mw_complete); > + ocfs2_track_lock_wait(lockres); > } > > return ret; > @@ -3098,7 +3120,7 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, > void *v, loff_t *pos) > * New in version 3 > * - Max time in lock stats is in usecs (instead of nsecs) > * New in version 4 > - * - Add last pr/ex unlock times in usecs > + * - Add last pr/ex unlock times and first lock wait time in usecs > */ > #define OCFS2_DLM_DEBUG_STR_VERSION 4 > static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) > @@ -3116,7 +3138,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void > *v) > return -EINVAL; > > #ifdef CONFIG_OCFS2_FS_STATS > - if (dlm_debug->d_filter_secs) { > + if (!lockres->l_lock_wait && dlm_debug->d_filter_secs) { > now = ktime_to_us(ktime_get_real()); > if (lockres->l_lock_prmode.ls_last > > lockres->l_lock_exmode.ls_last) > @@ -3177,6 +3199,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void > *v) > # define lock_refresh(_l) ((_l)->l_lock_refresh) > # define lock_last_prmode(_l) ((_l)->l_lock_prmode.ls_last) > # define lock_last_exmode(_l) ((_l)->l_lock_exmode.ls_last) > +# define lock_wait(_l) ((_l)->l_lock_wait) > #else > # define lock_num_prmode(_l) (0) > # define lock_num_exmode(_l) (0) > @@ -3189,6 +3212,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void > *v) > # define lock_refresh(_l) (0) > # define lock_last_prmode(_l) (0ULL) > # define lock_last_exmode(_l) (0ULL) > +# define lock_wait(_l) (0ULL) > #endif > /* The following seq_print was added in version 2 of this output */ > seq_printf(m, "%u\t" > @@ -3201,6 +3225,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void > *v) > "%u\t" > "%u\t" > "%llu\t" > + "%llu\t" > "%llu\t", > lock_num_prmode(lockres), > lock_num_exmode(lockres), > @@ -3212,7 +3237,8 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void > *v) > lock_max_exmode(lockres), > lock_refresh(lockres), > lock_last_prmode(lockres), > - lock_last_exmode(lockres)); > + lock_last_exmode(lockres), > + lock_wait(lockres)); > > /* End the line */ > seq_printf(m, "\n"); > diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h > index 6d0a77703d0e..99ce40063da6 100644 > --- a/fs/ocfs2/ocfs2.h > +++ b/fs/ocfs2/ocfs2.h > @@ -206,6 +206,7 @@ struct ocfs2_lock_res { > #ifdef CONFIG_OCFS2_FS_STATS > struct ocfs2_lock_stats l_lock_prmode; /* PR mode stats */ > u32 l_lock_refresh; /* Disk refreshes */ > + u64 l_lock_wait; /* First lock wait time */ > struct ocfs2_lock_stats l_lock_exmode; /* EX mode stats */ > #endif > #ifdef CONFIG_DEBUG_LOCK_ALLOC >