ocfs2: Use 64bit variables to track heartbeat time
PATCH v3 1/1 ocfs2: Use 64bit variables to track heartbeat time
o2hb_elapsed_msecs computes the time taken for a disk heartbeat. 'struct timeval' variables are used to store start and end times. On 32-bit systems, the 'tv_sec' component of 'struct timeval' will overflow in year 2038 and beyond.
This patch solves the overflow with the following:
1. Replace o2hb_elapsed_msecs using 'ktime_t' values to measure start and end time, and built-in function 'ktime_ms_delta' to compute the elapsed time.
ktime_get_real() is used since the code prints out the wallclock time.
2. Changes format string to print time as a single 64-bit nanoseconds value ("%lld") instead of seconds and microseconds. This simplifies the code since converting ktime_t to that format would need expensive computation. However, the debug log string is less readable than the previous format.
Suggested by: Arnd Bergmann <[email protected]>
---
Changes in v3:
- Remove usage of timespec64 as its inefficient, change the prints format string instead.
Changes in v2:
- Use ktime_t instead of timespec64 to simplify computation of elapsed time.
- Use ktime_ms_delta instead of timespec64_sub and dividing, since 32-bit kernel cannot divide a 64-bit number.
--- fs/ocfs2/cluster/heartbeat.c | 49 ++++++++------------------------------------ 1 file changed, 9 insertions(+), 40 deletions(-)
fs/ocfs2/cluster/heartbeat.c +9 -40
@@ -36,7 +36,7 @@#include <linux/debugfs.h> #include <linux/slab.h> #include <linux/bitmap.h> - +#include <linux/ktime.h> #include "heartbeat.h" #include "tcp.h" #include "nodemanager.h"
@@ -1061,37 +1061,6 @@ bail:return ret; } -/* Subtract b from a, storing the result in a. a *must* have a larger -* value than b. */ -static void o2hb_tv_subtract (struct timeval *a, -struct timeval *b) -{ -/* just return 0 when a is after b */ -if (a->tv_sec < b->tv_sec || - (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec)) { - a->tv_sec =0 ; - a->tv_usec =0 ; -return ; - } - - a->tv_sec -= b->tv_sec; - a->tv_usec -= b->tv_usec; -while ( a->tv_usec <0 ) { - a->tv_sec--; - a->tv_usec +=1000000 ; - } -} - -static unsigned int o2hb_elapsed_msecs (struct timeval *start, -struct timeval *end) -{ -struct timeval res = *end; - -o2hb_tv_subtract (&res, start); - -return res.tv_sec *1000 + res.tv_usec /1000 ; -} -/* * we ride the region ref that the region dir holds. before the region * dir is removed and drops it ref it will wait to tear down this
@@ -1102,7 +1071,7 @@ static int o2hb_thread(void *data)int i, ret;struct o2hb_region *reg = data;struct o2hb_bio_wait_ctxt write_wc; -struct timeval before_hb, after_hb; +ktime_t before_hb, after_hb;unsigned int elapsed_msec;mlog (ML_HEARTBEAT |ML_KTHREAD ,"hb thread running\n" );
@@ -1119,18 +1088,18 @@ static int o2hb_thread(void *data)* hr_timeout_ms between disk writes. On busy systems * this should result in a heartbeat which is less * likely to time itself out. */ -do_gettimeofday (&before_hb); + before_hb =ktime_get_real (); ret =o2hb_do_disk_heartbeat (reg); -do_gettimeofday (&after_hb); - elapsed_msec =o2hb_elapsed_msecs (&before_hb, &after_hb); + after_hb =ktime_get_real (); + + elapsed_msec = (unsigned int ) +ktime_ms_delta (after_hb, before_hb);mlog (ML_HEARTBEAT , -"start = %lu.%lu, end = %lu.%lu, msec = %u, ret = %d\n" , - before_hb.tv_sec, (unsigned long ) before_hb.tv_usec, - after_hb.tv_sec, (unsigned long ) after_hb.tv_usec, - elapsed_msec, ret); +"start = %lld, end = %lld, msec = %u, ret = %d\n" , + before_hb.tv64, after_hb.tv64, elapsed_msec, ret);if (!kthread_should_stop () && elapsed_msec < reg->hr_timeout_ms) {
Signature · 1 line
2.2.0.rc0.207.ga3a616c