From: Tina Ruchandani Date: Thu, 5 Jan 2017 14:53:30 +0000 (-0500) Subject: LU-4423 lnet: Better cookie gen X-Git-Tag: 2.9.52~9 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=2be59ff6bffdbaece48d35cd678bc9ee28ddf4f3 LU-4423 lnet: Better cookie gen api-ni.c uses do_gettimeofday to get a 'cookie' or timestamp. This patch replaces it with ktime_get_ns for the following reasons: 1. ktime_get_ns returns a __u64 which is safer than 'struct timeval' which will overflow on 32-bit systems in year 2038 and beyond. 2. Improved resolution: nsecs instead of usecs. 3. Reduced compute: ktime_get_ns is faster than the multiply/add combination used in this function Linux-commit: 9056be30542bfff51190bdda67088f319cf4c9f5 Drop unneeded wrapper function Remove the function lnet_create_interface_cookie() and replace its call with the function ktime_get_ns(). Linux-commit: 7bcd831b8579212303ec7c30e975432b914493dc The ln_interface_cookie is used to ensure that a node can tell whether the following sequence of events has happened: node sends GET or PUT to peer node is rebooted peer sends REPLY or ACK to node The ln_interface_cookie is set once, when LNet starts, and remains unchanged afterwards. To avoid accidentally obtaining the same cookie after a reboot, the code generated ths cookie using ktime_get_ns(). Once generated, the value of the cookie is not interpreted, only compared for equality. Olaf Weber reported that due to the use of ktime_get_ns() a small chance exist of generating a cookie of identical value across reboots. Using ktime_get_real_ns() removes any chance of this from happening. Change-Id: I159a0ff2573afb87f279a8e8f282b0ac076d9bf3 Signed-off-by: Tina Ruchandani Signed-off-by: Shivani Bhardwaj Suggested-by: Arnd Bergmann Reviewed-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/24682 Reviewed-by: Doug Oucharek Reviewed-by: Olaf Weber Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin --- diff --git a/libcfs/autoconf/lustre-libcfs.m4 b/libcfs/autoconf/lustre-libcfs.m4 index 95b25c0..3740297 100644 --- a/libcfs/autoconf/lustre-libcfs.m4 +++ b/libcfs/autoconf/lustre-libcfs.m4 @@ -365,6 +365,23 @@ ktime_get_real_seconds, [ ]) # LIBCFS_KTIME_GET_REAL_SECONDS # +# Kernel version 3.17 created ktime_get_ns wrapper +# +AC_DEFUN([LIBCFS_KTIME_GET_REAL_NS],[ +LB_CHECK_COMPILE([does function 'ktime_get_real_ns' exist], +ktime_get_ns, [ + #include +],[ + u64 nanoseconds; + + nanoseconds = ktime_get_real_ns(); +],[ + AC_DEFINE(HAVE_KTIME_GET_REAL_NS, 1, + ['ktime_get_real_ns' is available]) +]) +]) # LIBCFS_KTIME_GET_REAL_NS + +# # Kernel version 3.19 introduced ktime_get_seconds # AC_DEFUN([LIBCFS_KTIME_GET_SECONDS],[ @@ -505,6 +522,7 @@ LIBCFS_HLIST_ADD_AFTER LIBCFS_TIMESPEC64 LIBCFS_KTIME_GET_REAL_TS64 LIBCFS_KTIME_GET_REAL_SECONDS +LIBCFS_KTIME_GET_REAL_NS # 3.19 LIBCFS_KTIME_GET_SECONDS # 4.2 diff --git a/libcfs/include/libcfs/linux/linux-time.h b/libcfs/include/libcfs/linux/linux-time.h index e65d2f7..bf403ff 100644 --- a/libcfs/include/libcfs/linux/linux-time.h +++ b/libcfs/include/libcfs/linux/linux-time.h @@ -145,6 +145,13 @@ time64_t ktime_get_real_seconds(void); time64_t ktime_get_seconds(void); #endif /* HAVE_KTIME_GET_SECONDS */ +#ifndef HAVE_KTIME_GET_REAL_NS +static inline u64 ktime_get_real_ns(void) +{ + return ktime_to_ns(ktime_get_real()); +} +#endif /* HAVE_KTIME_GET_NS */ + static inline int cfs_time_before(cfs_time_t t1, cfs_time_t t2) { return time_before(t1, t2); diff --git a/lnet/lnet/api-ni.c b/lnet/lnet/api-ni.c index 16465b5..270629d 100644 --- a/lnet/lnet/api-ni.c +++ b/lnet/lnet/api-ni.c @@ -32,6 +32,8 @@ #define DEBUG_SUBSYSTEM S_LNET #include +#include + #include #define D_LNI D_CONSOLE @@ -396,21 +398,6 @@ lnet_counters_reset(void) lnet_net_unlock(LNET_LOCK_EX); } -static __u64 lnet_create_interface_cookie(void) -{ - /* NB the interface cookie in wire handles guards against delayed - * replies and ACKs appearing valid after reboot. Initialisation time, - * even if it's only implemented to millisecond resolution is probably - * easily good enough. */ - struct timeval tv; - __u64 cookie; - do_gettimeofday(&tv); - cookie = tv.tv_sec; - cookie *= 1000000; - cookie += tv.tv_usec; - return cookie; -} - static char * lnet_res_type2str(int type) { @@ -612,7 +599,11 @@ lnet_prepare(lnet_pid_t requested_pid) if (rc != 0) goto failed; - the_lnet.ln_interface_cookie = lnet_create_interface_cookie(); + /* + * NB the interface cookie in wire handles guards against delayed + * replies and ACKs appearing valid after reboot. + */ + the_lnet.ln_interface_cookie = ktime_get_real_ns(); the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(), sizeof(lnet_counters_t));