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 <a...@arndb.de>
Signed-off-by: Tina Ruchandani <ruchandani.t...@gmail.com>
---
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(-)

diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 16eff45..3a60c832 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -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) {
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to