ocfs2: Use hrtimer to track ocfs2 fs lock stats
PATCH 1/1 ocfs2: Use hrtimer to track ocfs2 fs lock stats
Patch makes use of the hrtimer to track times in ocfs2 lock stats.
The patch is a bit involved to ensure no additional impact on the memory footprint. The size of ocfs2_inode_cache remains 1280 bytes on 32-bit systems.
A related change was to modify the unit of the max wait time from nanosec to microsec allowing us to track max time larger than 4 secs. This change necessitated the bumping of the output version in the debugfs file, locking_state, from 2 to 3.
--- fs/ocfs2/dlmglue.c | 97 +++++++++++++++++++++++++++------------------------- fs/ocfs2/ocfs2.h | 23 +++++++----- 2 files changed, 64 insertions(+), 56 deletions(-)
fs/ocfs2/dlmglue.c +50 -47
@@ -64,7 +64,7 @@ struct ocfs2_mask_waiter {unsigned long mw_mask;unsigned long mw_goal;#ifdef CONFIG_OCFS2_FS_STATS -unsigned long long mw_lock_start; +ktime_t mw_lock_start;#endif };
@@ -435,44 +435,41 @@ static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res)#ifdef CONFIG_OCFS2_FS_STATS static void ocfs2_init_lock_stats (struct ocfs2_lock_res *res) { - res->l_lock_num_prmode =0 ; - res->l_lock_num_prmode_failed =0 ; - res->l_lock_total_prmode =0 ; - res->l_lock_max_prmode =0 ; - res->l_lock_num_exmode =0 ; - res->l_lock_num_exmode_failed =0 ; - res->l_lock_total_exmode =0 ; - res->l_lock_max_exmode =0 ; res->l_lock_refresh =0 ; +memset (&res->l_lock_prmode,0 ,sizeof (struct ocfs2_lock_stats )); +memset (&res->l_lock_exmode,0 ,sizeof (struct ocfs2_lock_stats )); }static void ocfs2_update_lock_stats (struct ocfs2_lock_res *res,int level,struct ocfs2_mask_waiter *mw,int ret) { -unsigned long long *num, *sum; -unsigned int *max, *failed; -struct timespec ts =current_kernel_time (); -unsigned long long time =timespec_to_ns (&ts) - mw->mw_lock_start; - -if (level ==LKM_PRMODE ) { - num = &res->l_lock_num_prmode; - sum = &res->l_lock_total_prmode; - max = &res->l_lock_max_prmode; - failed = &res->l_lock_num_prmode_failed; - }else if (level ==LKM_EXMODE ) { - num = &res->l_lock_num_exmode; - sum = &res->l_lock_total_exmode; - max = &res->l_lock_max_exmode; - failed = &res->l_lock_num_exmode_failed; - }else +u32 usec; +ktime_t kt; +struct ocfs2_lock_stats *stats; + +if (level ==LKM_PRMODE ) + stats = &res->l_lock_prmode; +else if (level ==LKM_EXMODE ) + stats = &res->l_lock_exmode; +else return ; - (*num)++; - (*sum) += time; -if (time > *max) - *max = time; + kt =ktime_sub (ktime_get (), mw->mw_lock_start); + usec =ktime_to_us (kt); + + stats->ls_gets++; + stats->ls_total +=ktime_to_ns (kt); +/* overflow */ +if (unlikely (stats->ls_gets) ==0 ) { + stats->ls_gets++; + stats->ls_total =ktime_to_ns (kt); + } + +if (stats->ls_max < usec) + stats->ls_max = usec; +if (ret) - (*failed)++; + stats->ls_fail++; }static inline void ocfs2_track_lock_refresh (struct ocfs2_lock_res *lockres)
@@ -482,8 +479,7 @@ static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres)static inline void ocfs2_init_start_time (struct ocfs2_mask_waiter *mw) { -struct timespec ts =current_kernel_time (); - mw->mw_lock_start =timespec_to_ns (&ts); + mw->mw_lock_start =ktime_get (); }#else static inline void ocfs2_init_lock_stats (struct ocfs2_lock_res *res)
@@ -2869,8 +2865,15 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos)return iter; } -/* So that debugfs.ocfs2 can determine which format is being used */ -#define OCFS2_DLM_DEBUG_STR_VERSION 2 +/* +* Version is used by debugfs.ocfs2 to determine the format being used +* +* New in version 2 +* - Lock stats printed +* New in version 3 +* - Max time in lock stats is in usecs (instead of nsecs) +*/ +#define OCFS2_DLM_DEBUG_STR_VERSION 3static int ocfs2_dlm_seq_show (struct seq_file *m,void *v) {int i;
@@ -2912,18 +2915,18 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)seq_printf (m,"0x%x\t" , lvb[i]);#ifdef CONFIG_OCFS2_FS_STATS -# define lock_num_prmode (_l) (_l)->l_lock_num_prmode -# define lock_num_exmode (_l) (_l)->l_lock_num_exmode -# define lock_num_prmode_failed (_l) (_l)->l_lock_num_prmode_failed -# define lock_num_exmode_failed (_l) (_l)->l_lock_num_exmode_failed -# define lock_total_prmode (_l) (_l)->l_lock_total_prmode -# define lock_total_exmode (_l) (_l)->l_lock_total_exmode -# define lock_max_prmode (_l) (_l)->l_lock_max_prmode -# define lock_max_exmode (_l) (_l)->l_lock_max_exmode -# define lock_refresh (_l) (_l)->l_lock_refresh +# define lock_num_prmode (_l) ((_l)->l_lock_prmode.ls_gets) +# define lock_num_exmode (_l) ((_l)->l_lock_exmode.ls_gets) +# define lock_num_prmode_failed (_l) ((_l)->l_lock_prmode.ls_fail) +# define lock_num_exmode_failed (_l) ((_l)->l_lock_exmode.ls_fail) +# define lock_total_prmode (_l) ((_l)->l_lock_prmode.ls_total) +# define lock_total_exmode (_l) ((_l)->l_lock_exmode.ls_total) +# define lock_max_prmode (_l) ((_l)->l_lock_prmode.ls_max) +# define lock_max_exmode (_l) ((_l)->l_lock_exmode.ls_max) +# define lock_refresh (_l) ((_l)->l_lock_refresh)#else -# define lock_num_prmode (_l) (0ULL) -# define lock_num_exmode (_l) (0ULL) +# define lock_num_prmode (_l) (0) +# define lock_num_exmode (_l) (0)# define lock_num_prmode_failed (_l) (0)# define lock_num_exmode_failed (_l) (0)# define lock_total_prmode (_l) (0ULL)
@@ -2933,8 +2936,8 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)# define lock_refresh (_l) (0)#endif /* The following seq_print was added in version 2 of this output */ -seq_printf (m,"%llu\t" -"%llu\t" +seq_printf (m,"%u\t" +"%u\t" "%u\t" "%u\t" "%llu\t"
fs/ocfs2/ocfs2.h +14 -9
@@ -147,6 +147,17 @@ struct ocfs2_lock_res_ops;typedef void (*ocfs2_lock_callback )(int status,unsigned long data); +#ifdef CONFIG_OCFS2_FS_STATS +struct ocfs2_lock_stats { +u64 ls_total;/* Total wait in NSEC */ +u32 ls_gets;/* Num acquires */ +u32 ls_fail;/* Num failed acquires */ + +/* Storing max wait in usecs saves 24 bytes per inode */ +u32 ls_max;/* Max wait in USEC */ +}; +#endif +struct ocfs2_lock_res {void *l_priv;struct ocfs2_lock_res_ops *l_ops;
@@ -182,15 +193,9 @@ struct ocfs2_lock_res {struct list_head l_debug_list;#ifdef CONFIG_OCFS2_FS_STATS -unsigned long long l_lock_num_prmode;/* PR acquires */ -unsigned long long l_lock_num_exmode;/* EX acquires */ -unsigned int l_lock_num_prmode_failed;/* Failed PR gets */ -unsigned int l_lock_num_exmode_failed;/* Failed EX gets */ -unsigned long long l_lock_total_prmode;/* Tot wait for PR */ -unsigned long long l_lock_total_exmode;/* Tot wait for EX */ -unsigned int l_lock_max_prmode;/* Max wait for PR */ -unsigned int l_lock_max_exmode;/* Max wait for EX */ -unsigned int l_lock_refresh;/* Disk refreshes */ +struct ocfs2_lock_stats l_lock_prmode;/* PR mode stats */ +u32 l_lock_refresh;/* Disk refreshes */ +struct ocfs2_lock_stats l_lock_exmode;/* EX mode stats */ #endif #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map l_lockdep_map;
Signature · 1 line
1.7.1
Joel Becker
maintainerPATCH 1/1 ocfs2: Use hrtimer to track ocfs2 fs lock stats
Quoted 11 lines · Sunil Mushran
Patch makes use of the hrtimer to track times in ocfs2 lock stats.
The patch is a bit involved to ensure no additional impact on the memory footprint. The size of
ocfs2_inode_cacheremains 1280 bytes on 32-bit systems.A related change was to modify the unit of the max wait time from nanosec to microsec allowing us to track max time larger than 4 secs. This change necessitated the bumping of the output version in the debugfs file,
locking_state, from 2 to 3.Signed-off-by Sunil Mushran <[email protected]>
This patch is now in the merge-window branch of ocfs2.git.
Joel
Signature · 6 lines
Life's Little Instruction Book #198 "Feed a stranger's expired parking meter." http://www.jlbec.org/ jlbec at evilplan.org