Commit 5bc970e8 authored by Sunil Mushran's avatar Sunil Mushran Committed by Joel Becker

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.
Signed-off-by: default avatarSunil Mushran <sunil.mushran@oracle.com>
Signed-off-by: default avatarJoel Becker <jlbec@evilplan.org>
parent 0cc9d525
......@@ -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 3
static 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"
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment