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: Sunil Mushran <sunil.mushran@oracle.com> Signed-off-by: Joel Becker <jlbec@evilplan.org>
This commit is contained in:
parent
0cc9d52578
commit
5bc970e803
|
@ -64,7 +64,7 @@ struct ocfs2_mask_waiter {
|
||||||
unsigned long mw_mask;
|
unsigned long mw_mask;
|
||||||
unsigned long mw_goal;
|
unsigned long mw_goal;
|
||||||
#ifdef CONFIG_OCFS2_FS_STATS
|
#ifdef CONFIG_OCFS2_FS_STATS
|
||||||
unsigned long long mw_lock_start;
|
ktime_t mw_lock_start;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -435,44 +435,41 @@ static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res)
|
||||||
#ifdef CONFIG_OCFS2_FS_STATS
|
#ifdef CONFIG_OCFS2_FS_STATS
|
||||||
static void ocfs2_init_lock_stats(struct ocfs2_lock_res *res)
|
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;
|
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,
|
static void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, int level,
|
||||||
struct ocfs2_mask_waiter *mw, int ret)
|
struct ocfs2_mask_waiter *mw, int ret)
|
||||||
{
|
{
|
||||||
unsigned long long *num, *sum;
|
u32 usec;
|
||||||
unsigned int *max, *failed;
|
ktime_t kt;
|
||||||
struct timespec ts = current_kernel_time();
|
struct ocfs2_lock_stats *stats;
|
||||||
unsigned long long time = timespec_to_ns(&ts) - mw->mw_lock_start;
|
|
||||||
|
|
||||||
if (level == LKM_PRMODE) {
|
if (level == LKM_PRMODE)
|
||||||
num = &res->l_lock_num_prmode;
|
stats = &res->l_lock_prmode;
|
||||||
sum = &res->l_lock_total_prmode;
|
else if (level == LKM_EXMODE)
|
||||||
max = &res->l_lock_max_prmode;
|
stats = &res->l_lock_exmode;
|
||||||
failed = &res->l_lock_num_prmode_failed;
|
else
|
||||||
} 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
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
(*num)++;
|
kt = ktime_sub(ktime_get(), mw->mw_lock_start);
|
||||||
(*sum) += time;
|
usec = ktime_to_us(kt);
|
||||||
if (time > *max)
|
|
||||||
*max = time;
|
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)
|
if (ret)
|
||||||
(*failed)++;
|
stats->ls_fail++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres)
|
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)
|
static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw)
|
||||||
{
|
{
|
||||||
struct timespec ts = current_kernel_time();
|
mw->mw_lock_start = ktime_get();
|
||||||
mw->mw_lock_start = timespec_to_ns(&ts);
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void ocfs2_init_lock_stats(struct ocfs2_lock_res *res)
|
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;
|
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)
|
static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
int i;
|
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]);
|
seq_printf(m, "0x%x\t", lvb[i]);
|
||||||
|
|
||||||
#ifdef CONFIG_OCFS2_FS_STATS
|
#ifdef CONFIG_OCFS2_FS_STATS
|
||||||
# define lock_num_prmode(_l) (_l)->l_lock_num_prmode
|
# define lock_num_prmode(_l) ((_l)->l_lock_prmode.ls_gets)
|
||||||
# define lock_num_exmode(_l) (_l)->l_lock_num_exmode
|
# define lock_num_exmode(_l) ((_l)->l_lock_exmode.ls_gets)
|
||||||
# define lock_num_prmode_failed(_l) (_l)->l_lock_num_prmode_failed
|
# define lock_num_prmode_failed(_l) ((_l)->l_lock_prmode.ls_fail)
|
||||||
# define lock_num_exmode_failed(_l) (_l)->l_lock_num_exmode_failed
|
# define lock_num_exmode_failed(_l) ((_l)->l_lock_exmode.ls_fail)
|
||||||
# define lock_total_prmode(_l) (_l)->l_lock_total_prmode
|
# define lock_total_prmode(_l) ((_l)->l_lock_prmode.ls_total)
|
||||||
# define lock_total_exmode(_l) (_l)->l_lock_total_exmode
|
# define lock_total_exmode(_l) ((_l)->l_lock_exmode.ls_total)
|
||||||
# define lock_max_prmode(_l) (_l)->l_lock_max_prmode
|
# define lock_max_prmode(_l) ((_l)->l_lock_prmode.ls_max)
|
||||||
# define lock_max_exmode(_l) (_l)->l_lock_max_exmode
|
# define lock_max_exmode(_l) ((_l)->l_lock_exmode.ls_max)
|
||||||
# define lock_refresh(_l) (_l)->l_lock_refresh
|
# define lock_refresh(_l) ((_l)->l_lock_refresh)
|
||||||
#else
|
#else
|
||||||
# define lock_num_prmode(_l) (0ULL)
|
# define lock_num_prmode(_l) (0)
|
||||||
# define lock_num_exmode(_l) (0ULL)
|
# define lock_num_exmode(_l) (0)
|
||||||
# define lock_num_prmode_failed(_l) (0)
|
# define lock_num_prmode_failed(_l) (0)
|
||||||
# define lock_num_exmode_failed(_l) (0)
|
# define lock_num_exmode_failed(_l) (0)
|
||||||
# define lock_total_prmode(_l) (0ULL)
|
# 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)
|
# define lock_refresh(_l) (0)
|
||||||
#endif
|
#endif
|
||||||
/* The following seq_print was added in version 2 of this output */
|
/* The following seq_print was added in version 2 of this output */
|
||||||
seq_printf(m, "%llu\t"
|
seq_printf(m, "%u\t"
|
||||||
"%llu\t"
|
"%u\t"
|
||||||
"%u\t"
|
"%u\t"
|
||||||
"%u\t"
|
"%u\t"
|
||||||
"%llu\t"
|
"%llu\t"
|
||||||
|
|
|
@ -147,6 +147,17 @@ struct ocfs2_lock_res_ops;
|
||||||
|
|
||||||
typedef void (*ocfs2_lock_callback)(int status, unsigned long data);
|
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 {
|
struct ocfs2_lock_res {
|
||||||
void *l_priv;
|
void *l_priv;
|
||||||
struct ocfs2_lock_res_ops *l_ops;
|
struct ocfs2_lock_res_ops *l_ops;
|
||||||
|
@ -182,15 +193,9 @@ struct ocfs2_lock_res {
|
||||||
struct list_head l_debug_list;
|
struct list_head l_debug_list;
|
||||||
|
|
||||||
#ifdef CONFIG_OCFS2_FS_STATS
|
#ifdef CONFIG_OCFS2_FS_STATS
|
||||||
unsigned long long l_lock_num_prmode; /* PR acquires */
|
struct ocfs2_lock_stats l_lock_prmode; /* PR mode stats */
|
||||||
unsigned long long l_lock_num_exmode; /* EX acquires */
|
u32 l_lock_refresh; /* Disk refreshes */
|
||||||
unsigned int l_lock_num_prmode_failed; /* Failed PR gets */
|
struct ocfs2_lock_stats l_lock_exmode; /* EX mode stats */
|
||||||
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 */
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||||
struct lockdep_map l_lockdep_map;
|
struct lockdep_map l_lockdep_map;
|
||||||
|
|
Loading…
Reference in New Issue