Commit 5bc970e803ad2b1f26771f39376a79dbf0f5bf64

Authored by Sunil Mushran
Committed by Joel Becker
1 parent 0cc9d52578

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>

Showing 2 changed files with 64 additions and 56 deletions Side-by-side Diff

... ... @@ -64,7 +64,7 @@
64 64 unsigned long mw_mask;
65 65 unsigned long mw_goal;
66 66 #ifdef CONFIG_OCFS2_FS_STATS
67   - unsigned long long mw_lock_start;
  67 + ktime_t mw_lock_start;
68 68 #endif
69 69 };
70 70  
71 71  
72 72  
73 73  
74 74  
75 75  
... ... @@ -435,44 +435,41 @@
435 435 #ifdef CONFIG_OCFS2_FS_STATS
436 436 static 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 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  
449 443 static void ocfs2_update_lock_stats(struct ocfs2_lock_res *res, int level,
450 444 struct ocfs2_mask_waiter *mw, int ret)
451 445 {
452   - unsigned long long *num, *sum;
453   - unsigned int *max, *failed;
454   - struct timespec ts = current_kernel_time();
455   - unsigned long long time = timespec_to_ns(&ts) - mw->mw_lock_start;
  446 + u32 usec;
  447 + ktime_t kt;
  448 + struct ocfs2_lock_stats *stats;
456 449  
457   - if (level == LKM_PRMODE) {
458   - num = &res->l_lock_num_prmode;
459   - sum = &res->l_lock_total_prmode;
460   - max = &res->l_lock_max_prmode;
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
  450 + if (level == LKM_PRMODE)
  451 + stats = &res->l_lock_prmode;
  452 + else if (level == LKM_EXMODE)
  453 + stats = &res->l_lock_exmode;
  454 + else
468 455 return;
469 456  
470   - (*num)++;
471   - (*sum) += time;
472   - if (time > *max)
473   - *max = time;
  457 + kt = ktime_sub(ktime_get(), mw->mw_lock_start);
  458 + usec = ktime_to_us(kt);
  459 +
  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 471 if (ret)
475   - (*failed)++;
  472 + stats->ls_fail++;
476 473 }
477 474  
478 475 static inline void ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres)
... ... @@ -482,8 +479,7 @@
482 479  
483 480 static inline void ocfs2_init_start_time(struct ocfs2_mask_waiter *mw)
484 481 {
485   - struct timespec ts = current_kernel_time();
486   - mw->mw_lock_start = timespec_to_ns(&ts);
  482 + mw->mw_lock_start = ktime_get();
487 483 }
488 484 #else
489 485 static inline void ocfs2_init_lock_stats(struct ocfs2_lock_res *res)
... ... @@ -2869,8 +2865,15 @@
2869 2865 return iter;
2870 2866 }
2871 2867  
2872   -/* So that debugfs.ocfs2 can determine which format is being used */
2873   -#define OCFS2_DLM_DEBUG_STR_VERSION 2
  2868 +/*
  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
2874 2877 static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
2875 2878 {
2876 2879 int i;
2877 2880  
... ... @@ -2912,18 +2915,18 @@
2912 2915 seq_printf(m, "0x%x\t", lvb[i]);
2913 2916  
2914 2917 #ifdef CONFIG_OCFS2_FS_STATS
2915   -# define lock_num_prmode(_l) (_l)->l_lock_num_prmode
2916   -# define lock_num_exmode(_l) (_l)->l_lock_num_exmode
2917   -# define lock_num_prmode_failed(_l) (_l)->l_lock_num_prmode_failed
2918   -# define lock_num_exmode_failed(_l) (_l)->l_lock_num_exmode_failed
2919   -# define lock_total_prmode(_l) (_l)->l_lock_total_prmode
2920   -# define lock_total_exmode(_l) (_l)->l_lock_total_exmode
2921   -# define lock_max_prmode(_l) (_l)->l_lock_max_prmode
2922   -# define lock_max_exmode(_l) (_l)->l_lock_max_exmode
2923   -# define lock_refresh(_l) (_l)->l_lock_refresh
  2918 +# define lock_num_prmode(_l) ((_l)->l_lock_prmode.ls_gets)
  2919 +# define lock_num_exmode(_l) ((_l)->l_lock_exmode.ls_gets)
  2920 +# define lock_num_prmode_failed(_l) ((_l)->l_lock_prmode.ls_fail)
  2921 +# define lock_num_exmode_failed(_l) ((_l)->l_lock_exmode.ls_fail)
  2922 +# define lock_total_prmode(_l) ((_l)->l_lock_prmode.ls_total)
  2923 +# define lock_total_exmode(_l) ((_l)->l_lock_exmode.ls_total)
  2924 +# define lock_max_prmode(_l) ((_l)->l_lock_prmode.ls_max)
  2925 +# define lock_max_exmode(_l) ((_l)->l_lock_exmode.ls_max)
  2926 +# define lock_refresh(_l) ((_l)->l_lock_refresh)
2924 2927 #else
2925   -# define lock_num_prmode(_l) (0ULL)
2926   -# define lock_num_exmode(_l) (0ULL)
  2928 +# define lock_num_prmode(_l) (0)
  2929 +# define lock_num_exmode(_l) (0)
2927 2930 # define lock_num_prmode_failed(_l) (0)
2928 2931 # define lock_num_exmode_failed(_l) (0)
2929 2932 # define lock_total_prmode(_l) (0ULL)
... ... @@ -2933,8 +2936,8 @@
2933 2936 # define lock_refresh(_l) (0)
2934 2937 #endif
2935 2938 /* The following seq_print was added in version 2 of this output */
2936   - seq_printf(m, "%llu\t"
2937   - "%llu\t"
  2939 + seq_printf(m, "%u\t"
  2940 + "%u\t"
2938 2941 "%u\t"
2939 2942 "%u\t"
2940 2943 "%llu\t"
... ... @@ -147,6 +147,17 @@
147 147  
148 148 typedef void (*ocfs2_lock_callback)(int status, unsigned long data);
149 149  
  150 +#ifdef CONFIG_OCFS2_FS_STATS
  151 +struct 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 +
150 161 struct ocfs2_lock_res {
151 162 void *l_priv;
152 163 struct ocfs2_lock_res_ops *l_ops;
... ... @@ -182,15 +193,9 @@
182 193 struct list_head l_debug_list;
183 194  
184 195 #ifdef CONFIG_OCFS2_FS_STATS
185   - unsigned long long l_lock_num_prmode; /* PR acquires */
186   - unsigned long long l_lock_num_exmode; /* EX acquires */
187   - unsigned int l_lock_num_prmode_failed; /* Failed PR gets */
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 */
  196 + struct ocfs2_lock_stats l_lock_prmode; /* PR mode stats */
  197 + u32 l_lock_refresh; /* Disk refreshes */
  198 + struct ocfs2_lock_stats l_lock_exmode; /* EX mode stats */
194 199 #endif
195 200 #ifdef CONFIG_DEBUG_LOCK_ALLOC
196 201 struct lockdep_map l_lockdep_map;