On 19/6/12 15:29, Gang He wrote:
> Hello Joseph,
> 
>>>> On 6/12/2019 at  3:03 pm, in message
> <fe52ae81-2140-9f68-8ec2-cc7c1fb3b...@linux.alibaba.com>, Joseph Qi
> <joseph...@linux.alibaba.com> wrote:
>> 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?
> The new item l_lock_wait is a statistic (or debugging) related, which will be 
> dumping to the user-space via debugfs file locking_state for the further 
> analysis if need.
> As the last comments from Wengang, the dumping is from different nodes in the 
> cluster, it is better to use wall time (instead of mono or boot time) to 
> display the related absolute times.
> Of course, the existing delta time (use mono time) will not affected.
> 
> Thanks
> Gang
> 
Got it,

Reviewed-by: Joseph Qi <joseph...@linux.alibaba.com>

>>
>> 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
>>>

Reply via email to