aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSunil Mushran <sunil.mushran@oracle.com>2010-12-29 02:26:03 -0500
committerJoel Becker <jlbec@evilplan.org>2011-02-20 06:56:07 -0500
commit5bc970e803ad2b1f26771f39376a79dbf0f5bf64 (patch)
treecc2c0dd4a49ddad9691d0ef0312475db76bc6464
parent0cc9d5257857608ba85885b75fcada13d359b5d1 (diff)
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>
-rw-r--r--fs/ocfs2/dlmglue.c97
-rw-r--r--fs/ocfs2/ocfs2.h23
2 files changed, 64 insertions, 56 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index e8d94d722ec..7484bb9a343 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -64,7 +64,7 @@ struct ocfs2_mask_waiter {
64 unsigned long mw_mask; 64 unsigned long mw_mask;
65 unsigned long mw_goal; 65 unsigned long mw_goal;
66#ifdef CONFIG_OCFS2_FS_STATS 66#ifdef CONFIG_OCFS2_FS_STATS
67 unsigned long long mw_lock_start; 67 ktime_t mw_lock_start;
68#endif 68#endif
69}; 69};
70 70
@@ -435,44 +435,41 @@ static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res)
435#ifdef CONFIG_OCFS2_FS_STATS 435#ifdef CONFIG_OCFS2_FS_STATS
436static void ocfs2_init_lock_stats(struct ocfs2_lock_res *res) 436static void ocfs2_init_lock_stats(struct ocfs2_lock_res *res)
437{ 437{
438 res->l_lock_num_prmode = 0;
439 res->l_lock_num_prmode_failed = 0;
440 res->l_lock_total_prmode = 0;
441 res->l_lock_max_prmode = 0;
442 res->l_lock_num_exmode = 0;
443 res->l_lock_num_exmode_failed = 0;
444 res->l_lock_total_exmode = 0;
445 res->l_lock_max_exmode = 0;
446 res->l_lock_refresh = 0; 438 res->l_lock_refresh = 0;
439 memset(&res->l_lock_prmode, 0, sizeof(struct ocfs2_lock_stats));
440 memset(&res->l_lock_exmode, 0, sizeof(struct ocfs2_lock_stats));
447} 441}
448 442
449static void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, int level, 443static void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, int level,
450 struct ocfs2_mask_waiter *mw, int ret) 444 struct ocfs2_mask_waiter *mw, int ret)
451{ 445{
452 unsigned long long *num, *sum; 446 u32 usec;
453 unsigned int *max, *failed; 447 ktime_t kt;
454 struct timespec ts = current_kernel_time(); 448 struct ocfs2_lock_stats *stats;
455 unsigned long long time = timespec_to_ns(&ts) - mw->mw_lock_start; 449
456 450 if (level == LKM_PRMODE)
457 if (level == LKM_PRMODE) { 451 stats = &res->l_lock_prmode;
458 num = &res->l_lock_num_prmode; 452 else if (level == LKM_EXMODE)
459 sum = &res->l_lock_total_prmode; 453 stats = &res->l_lock_exmode;
460 max = &res->l_lock_max_prmode; 454 else
461 failed = &res->l_lock_num_prmode_failed;
462 } else if (level == LKM_EXMODE) {
463 num = &res->l_lock_num_exmode;
464 sum = &res->l_lock_total_exmode;
465 max = &res->l_lock_max_exmode;
466 failed = &res->l_lock_num_exmode_failed;
467 } else
468 return; 455 return;
469 456
470 (*num)++; 457 kt = ktime_sub(ktime_get(), mw->mw_lock_start);
471 (*sum) += time; 458 usec = ktime_to_us(kt);
472 if (time > *max) 459
473 *max = time; 460 stats->ls_gets++;
461 stats->ls_total += ktime_to_ns(kt);
462 /* overflow */
463 if (unlikely(stats->ls_gets) == 0) {
464 stats->ls_gets++;
465 stats->ls_total = ktime_to_ns(kt);
466 }
467
468 if (stats->ls_max < usec)
469 stats->ls_max = usec;
470
474 if (ret) 471 if (ret)
475 (*failed)++; 472 stats->ls_fail++;
476} 473}
477 474
478static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres) 475static 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)
482 479
483static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw) 480static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw)
484{ 481{
485 struct timespec ts = current_kernel_time(); 482 mw->mw_lock_start = ktime_get();
486 mw->mw_lock_start = timespec_to_ns(&ts);
487} 483}
488#else 484#else
489static inline void ocfs2_init_lock_stats(struct ocfs2_lock_res *res) 485static 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)
2869 return iter; 2865 return iter;
2870} 2866}
2871 2867
2872/* So that debugfs.ocfs2 can determine which format is being used */ 2868/*
2873#define OCFS2_DLM_DEBUG_STR_VERSION 2 2869 * Version is used by debugfs.ocfs2 to determine the format being used
2870 *
2871 * New in version 2
2872 * - Lock stats printed
2873 * New in version 3
2874 * - Max time in lock stats is in usecs (instead of nsecs)
2875 */
2876#define OCFS2_DLM_DEBUG_STR_VERSION 3
2874static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) 2877static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
2875{ 2878{
2876 int i; 2879 int i;
@@ -2912,18 +2915,18 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
2912 seq_printf(m, "0x%x\t", lvb[i]); 2915 seq_printf(m, "0x%x\t", lvb[i]);
2913 2916
2914#ifdef CONFIG_OCFS2_FS_STATS 2917#ifdef CONFIG_OCFS2_FS_STATS
2915# define lock_num_prmode(_l) (_l)->l_lock_num_prmode 2918# define lock_num_prmode(_l) ((_l)->l_lock_prmode.ls_gets)
2916# define lock_num_exmode(_l) (_l)->l_lock_num_exmode 2919# define lock_num_exmode(_l) ((_l)->l_lock_exmode.ls_gets)
2917# define lock_num_prmode_failed(_l) (_l)->l_lock_num_prmode_failed 2920# define lock_num_prmode_failed(_l) ((_l)->l_lock_prmode.ls_fail)
2918# define lock_num_exmode_failed(_l) (_l)->l_lock_num_exmode_failed 2921# define lock_num_exmode_failed(_l) ((_l)->l_lock_exmode.ls_fail)
2919# define lock_total_prmode(_l) (_l)->l_lock_total_prmode 2922# define lock_total_prmode(_l) ((_l)->l_lock_prmode.ls_total)
2920# define lock_total_exmode(_l) (_l)->l_lock_total_exmode 2923# define lock_total_exmode(_l) ((_l)->l_lock_exmode.ls_total)
2921# define lock_max_prmode(_l) (_l)->l_lock_max_prmode 2924# define lock_max_prmode(_l) ((_l)->l_lock_prmode.ls_max)
2922# define lock_max_exmode(_l) (_l)->l_lock_max_exmode 2925# define lock_max_exmode(_l) ((_l)->l_lock_exmode.ls_max)
2923# define lock_refresh(_l) (_l)->l_lock_refresh 2926# define lock_refresh(_l) ((_l)->l_lock_refresh)
2924#else 2927#else
2925# define lock_num_prmode(_l) (0ULL) 2928# define lock_num_prmode(_l) (0)
2926# define lock_num_exmode(_l) (0ULL) 2929# define lock_num_exmode(_l) (0)
2927# define lock_num_prmode_failed(_l) (0) 2930# define lock_num_prmode_failed(_l) (0)
2928# define lock_num_exmode_failed(_l) (0) 2931# define lock_num_exmode_failed(_l) (0)
2929# define lock_total_prmode(_l) (0ULL) 2932# define lock_total_prmode(_l) (0ULL)
@@ -2933,8 +2936,8 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
2933# define lock_refresh(_l) (0) 2936# define lock_refresh(_l) (0)
2934#endif 2937#endif
2935 /* The following seq_print was added in version 2 of this output */ 2938 /* The following seq_print was added in version 2 of this output */
2936 seq_printf(m, "%llu\t" 2939 seq_printf(m, "%u\t"
2937 "%llu\t" 2940 "%u\t"
2938 "%u\t" 2941 "%u\t"
2939 "%u\t" 2942 "%u\t"
2940 "%llu\t" 2943 "%llu\t"
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 51cd6898e7f..4e3d3c1363f 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -147,6 +147,17 @@ struct ocfs2_lock_res_ops;
147 147
148typedef void (*ocfs2_lock_callback)(int status, unsigned long data); 148typedef void (*ocfs2_lock_callback)(int status, unsigned long data);
149 149
150#ifdef CONFIG_OCFS2_FS_STATS
151struct ocfs2_lock_stats {
152 u64 ls_total; /* Total wait in NSEC */
153 u32 ls_gets; /* Num acquires */
154 u32 ls_fail; /* Num failed acquires */
155
156 /* Storing max wait in usecs saves 24 bytes per inode */
157 u32 ls_max; /* Max wait in USEC */
158};
159#endif
160
150struct ocfs2_lock_res { 161struct ocfs2_lock_res {
151 void *l_priv; 162 void *l_priv;
152 struct ocfs2_lock_res_ops *l_ops; 163 struct ocfs2_lock_res_ops *l_ops;
@@ -182,15 +193,9 @@ struct ocfs2_lock_res {
182 struct list_head l_debug_list; 193 struct list_head l_debug_list;
183 194
184#ifdef CONFIG_OCFS2_FS_STATS 195#ifdef CONFIG_OCFS2_FS_STATS
185 unsigned long long l_lock_num_prmode; /* PR acquires */ 196 struct ocfs2_lock_stats l_lock_prmode; /* PR mode stats */
186 unsigned long long l_lock_num_exmode; /* EX acquires */ 197 u32 l_lock_refresh; /* Disk refreshes */
187 unsigned int l_lock_num_prmode_failed; /* Failed PR gets */ 198 struct ocfs2_lock_stats l_lock_exmode; /* EX mode stats */
188 unsigned int l_lock_num_exmode_failed; /* Failed EX gets */
189 unsigned long long l_lock_total_prmode; /* Tot wait for PR */
190 unsigned long long l_lock_total_exmode; /* Tot wait for EX */
191 unsigned int l_lock_max_prmode; /* Max wait for PR */
192 unsigned int l_lock_max_exmode; /* Max wait for EX */
193 unsigned int l_lock_refresh; /* Disk refreshes */
194#endif 199#endif
195#ifdef CONFIG_DEBUG_LOCK_ALLOC 200#ifdef CONFIG_DEBUG_LOCK_ALLOC
196 struct lockdep_map l_lockdep_map; 201 struct lockdep_map l_lockdep_map;