Whamcloud - gitweb
LU-13344 lnet: stop using struct timeval 05/38105/21
authorJames Simmons <jsimmons@infradead.org>
Wed, 6 May 2020 21:41:58 +0000 (17:41 -0400)
committerOleg Drokin <green@whamcloud.com>
Thu, 14 May 2020 05:40:10 +0000 (05:40 +0000)
The struct timeval is not 2038 safe so the Linux kernel is moving
away from its use. The use of rpe_stamp hasn't been used since
Lustre 2.2 so remove the userland use of this field. This frees
use to change rpe_stamp to an equivalent struct timespec64 for
future use. Greatly simplify lnet_sock_[read|write] by using
jiffies values of sk_sndtimeo, sk_rcvtimeo cached in struct sock.

Change-Id: Ib58193756ec4a526e55bc810c05abd3920b2b269
Signed-off-by: James Simmons <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/38105
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Tested-by: Maloo <maloo@whamcloud.com>
libcfs/autoconf/lustre-libcfs.m4
libcfs/include/libcfs/linux/linux-time.h
lnet/include/uapi/linux/lnet/lnetst.h
lnet/lnet/lib-socket.c
lnet/selftest/conctl.c
lnet/selftest/conrpc.c
lnet/selftest/conrpc.h
lnet/selftest/console.h
lnet/utils/lst.c
lustre/include/uapi/linux/lustre/lustre_user.h

index ea62bf7..4346553 100644 (file)
@@ -219,6 +219,26 @@ EXTRA_KCFLAGS="$tmp_flags"
 ]) # LIBCFS_IOV_ITER_HAS_TYPE
 
 #
+# LIBCFS_HAVE_NS_TO_TIMESPEC64
+#
+# Kernel version 4.16-rc3 commit a84d1169164b274f13b97a23ff235c000efe3b49
+# introduced struct __kernel_old_timeval
+#
+AC_DEFUN([LIBCFS_HAVE_NS_TO_TIMESPEC64],[
+LB_CHECK_COMPILE([does 'ns_to_timespec64()' exist],
+kernel_old_timeval, [
+       #include <linux/time.h>
+],[
+       struct timespec64 kts;
+
+       kts = ns_to_timespec64(0);
+],[
+       AC_DEFINE(HAVE_NS_TO_TIMESPEC64, 1,
+               [ns_to_timespec64() is available])
+])
+]) # LIBCFS_HAVE_NS_TO_TIMESPEC64
+
+#
 # Kernel version 3.17 changed hlist_add_after to
 # hlist_add_behind
 #
@@ -1246,6 +1266,8 @@ LIBCFS_KTIME_COMPARE
 LIBCFS_SHRINKER_COUNT
 # 3.15
 LIBCFS_IOV_ITER_HAS_TYPE
+# 3.16
+LIBCFS_HAVE_NS_TO_TIMESPEC64
 # 3.17
 LIBCFS_HLIST_ADD_AFTER
 LIBCFS_TIMESPEC64
index 5af8134..3934635 100644 (file)
@@ -98,6 +98,26 @@ static inline struct timespec timespec64_to_timespec(const struct timespec64 ts6
 
 #endif /* HAVE_TIMESPEC64 */
 
+#ifndef HAVE_NS_TO_TIMESPEC64
+static inline struct timespec64 ns_to_timespec64(const s64 nsec)
+{
+       struct timespec64 ts;
+       s32 rem;
+
+       if (!nsec)
+               return (struct timespec64) {0, 0};
+
+       ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem);
+       if (unlikely(rem < 0)) {
+               ts.tv_sec--;
+               rem += NSEC_PER_SEC;
+       }
+       ts.tv_nsec = rem;
+
+       return ts;
+}
+#endif
+
 #ifndef HAVE_KTIME_ADD
 # define ktime_add(lhs, rhs) ({ (ktime_t){ .tv64 = (lhs).tv64 + (rhs).tv64 }; })
 #endif /* !HAVE_KTIME_ADD */
index bce9477..3c512b0 100644 (file)
@@ -136,7 +136,13 @@ struct list_head {
 struct lstcon_rpc_ent {
        struct list_head        rpe_link;               /* link chain */
        struct lnet_process_id  rpe_peer;               /* peer's id */
-       struct timeval          rpe_stamp;              /* time stamp of RPC */
+       /* This has not been used since Lustre 2.2 so its safe to use.
+        * Update to allow future use of timespec64
+        */
+       struct {
+               __s64           tv_sec;
+               __s64           tv_nsec;
+       } rpe_stamp;                                    /* time stamp of RPC */
        int                     rpe_state;              /* peer's state */
        int                     rpe_rpc_errno;          /* RPC errno */
 
index 5974818..a3628da 100644 (file)
 #include <net/sock.h>
 #include <linux/inetdevice.h>
 
+#include <libcfs/linux/linux-time.h>
 #include <libcfs/libcfs.h>
 #include <lnet/lib-lnet.h>
 
-/*
- * kernel 5.1: commit 7f1bc6e95d7840d4305595b3e4025cddda88cee5
- * Y2038 64-bit time.
- *  SO_TIMESTAMP, SO_TIMESTAMPNS and SO_TIMESTAMPING options, the
- *  way they are currently defined, are not y2038 safe.
- *  Subsequent patches in the series add new y2038 safe versions
- *  of these options which provide 64 bit timestamps on all
- *  architectures uniformly.
- *  Hence, rename existing options with OLD tag suffixes.
- *
- * NOTE: When updating to timespec64 change change these to '_NEW'.
- *
- */
-#ifndef SO_SNDTIMEO
-#define SO_SNDTIMEO SO_SNDTIMEO_OLD
-#endif
-
-#ifndef SO_RCVTIMEO
-#define SO_RCVTIMEO SO_RCVTIMEO_OLD
-#endif
-
 int
 lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
 {
-       int             rc;
-       long            jiffies_left = cfs_time_seconds(timeout);
-       unsigned long   then;
-       struct timeval  tv;
+       int rc;
+       long jiffies_left = cfs_time_seconds(timeout);
+       unsigned long then;
 
        LASSERT(nob > 0);
        /* Caller may pass a zero timeout if she thinks the socket buffer is
@@ -87,16 +66,12 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
                };
 
                if (timeout != 0) {
+                       struct sock *sk = sock->sk;
+
                        /* Set send timeout to remaining time */
-                       jiffies_to_timeval(jiffies_left, &tv);
-                       rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
-                                              (char *)&tv, sizeof(tv));
-                       if (rc != 0) {
-                               CERROR("Can't set socket send timeout "
-                                      "%ld.%06d: %d\n",
-                                      (long)tv.tv_sec, (int)tv.tv_usec, rc);
-                               return rc;
-                       }
+                       lock_sock(sk);
+                       sk->sk_sndtimeo = jiffies_left;
+                       release_sock(sk);
                }
 
                then = jiffies;
@@ -127,10 +102,9 @@ EXPORT_SYMBOL(lnet_sock_write);
 int
 lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
 {
-       int             rc;
-       long            jiffies_left = cfs_time_seconds(timeout);
-       unsigned long   then;
-       struct timeval  tv;
+       int rc;
+       long jiffies_left = cfs_time_seconds(timeout);
+       unsigned long then;
 
        LASSERT(nob > 0);
        LASSERT(jiffies_left > 0);
@@ -143,16 +117,12 @@ lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
                struct msghdr msg = {
                        .msg_flags      = 0
                };
+               struct sock *sk = sock->sk;
 
                /* Set receive timeout to remaining time */
-               jiffies_to_timeval(jiffies_left, &tv);
-               rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
-                                      (char *)&tv, sizeof(tv));
-               if (rc != 0) {
-                       CERROR("Can't set socket recv timeout %ld.%06d: %d\n",
-                              (long)tv.tv_sec, (int)tv.tv_usec, rc);
-                       return rc;
-               }
+               lock_sock(sk);
+               sk->sk_rcvtimeo = jiffies_left;
+               release_sock(sk);
 
                then = jiffies;
                rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0);
index 642a878..7ce53bb 100644 (file)
@@ -38,7 +38,6 @@
 
 #include <libcfs/libcfs.h>
 #include <lnet/lib-lnet.h>
-#include <uapi/linux/lnet/lnetst.h>
 #include "console.h"
 
 static int
index 6b3200d..a3ffa45 100644 (file)
@@ -471,7 +471,7 @@ lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans,
        struct lstcon_rpc *crpc;
        struct srpc_msg *msg;
        struct lstcon_node *nd;
-       struct timeval tv;
+       struct timespec64 ts;
        int error;
        s64 dur;
 
@@ -499,11 +499,11 @@ lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans,
 
                dur = crpc->crp_stamp_ns -
                      console_session.ses_id.ses_stamp * NSEC_PER_MSEC;
-               tv = ns_to_timeval(dur);
+               ts = ns_to_timespec64(dur);
 
                if (copy_to_user(&ent->rpe_peer,
                                 &nd->nd_id, sizeof(struct lnet_process_id)) ||
-                   copy_to_user(&ent->rpe_stamp, &tv, sizeof(tv)) ||
+                   copy_to_user(&ent->rpe_stamp, &ts, sizeof(ts)) ||
                    copy_to_user(&ent->rpe_state,
                                 &nd->nd_state, sizeof(nd->nd_state)) ||
                    copy_to_user(&ent->rpe_rpc_errno, &error,
index bdceea6..d7b4003 100644 (file)
@@ -41,7 +41,6 @@
 
 #include <libcfs/libcfs.h>
 #include <lnet/lib-types.h>
-#include <uapi/linux/lnet/lnetst.h>
 #include "rpc.h"
 #include "selftest.h"
 
index 09cd0e8..02c76a8 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <libcfs/libcfs.h>
 #include <lnet/lib-types.h>
-#include <uapi/linux/lnet/lnetst.h>
 #include "selftest.h"
 #include "conrpc.h"
 
index cd3a6cd..3509137 100644 (file)
@@ -44,6 +44,7 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <time.h>
+#include <linux/types.h>
 
 #include <libcfs/util/list.h>
 #include <libcfs/util/ioctl.h>
@@ -1630,20 +1631,6 @@ lst_lnet_stat_value(int bw, int send, int off)
 }
 
 static void
-lst_timeval_diff(struct timeval *tv1,
-                struct timeval *tv2, struct timeval *df)
-{
-       if (tv1->tv_usec >= tv2->tv_usec) {
-               df->tv_sec  = tv1->tv_sec - tv2->tv_sec;
-               df->tv_usec = tv1->tv_usec - tv2->tv_usec;
-               return;
-       }
-
-       df->tv_sec  = tv1->tv_sec - 1 - tv2->tv_sec;
-       df->tv_usec = tv1->tv_usec + 1000000 - tv2->tv_usec;
-}
-
-static void
 lst_cal_lnet_stat(float delta, struct lnet_counters_common *lnet_new,
                  struct lnet_counters_common *lnet_old, int mbs)
 {
@@ -1831,26 +1818,16 @@ lst_print_stat(char *name, struct list_head *resultp,
                lnet_old = (struct lnet_counters_common *)((char *)srpc_old +
                                                           sizeof(*srpc_old));
 
-               /* Prior to version 2.3, the running_ms field was a counter for
-                * the number of running tests.  We are looking at this value
-                * to determine if it is a millisecond timestamep (>= 2.3) or a
-                * test counter (< 2.3).  The number 500 is being used for this
-                * barrier as the test counter should never get this high, and
-                * the timestamp should never get this low.
+               /* Prior to version 2.3, the running_ms was a counter for
+                * the number of running tests. Since 2.3, running_ms is
+                * changed to hold the millisecond since the start of
+                * the work item. The rpe_stamp field was formerly used,
+                * but is no longer. In 2.12 rpe_stamp was changed to
+                * struct timespec64 and has nanosecond resolution, in
+                * case it is needed in the future.
                 */
-               if (sfwk_new->running_ms > 500) {
-                       /* use the timestamp from the remote node, not our
-                        * rpe_stamp from when we copied up the data out of
-                        * the kernel.
-                        */
-                       delta = (float)(sfwk_new->running_ms -
-                                       sfwk_old->running_ms) / 1000;
-               } else {
-                       struct timeval tv;
-
-                       lst_timeval_diff(&new->rpe_stamp, &old->rpe_stamp, &tv);
-                       delta = tv.tv_sec + (float)tv.tv_usec / 1000000;
-               }
+               delta = (float)(sfwk_new->running_ms -
+                               sfwk_old->running_ms) / 1000;
 
                if (!lnet) /* TODO */
                        continue;
index 65e41f1..a837ef1 100644 (file)
@@ -1273,7 +1273,7 @@ struct identity_downcall_data {
 
 struct sepol_downcall_data {
        __u32           sdd_magic;
-       __kernel_time_t sdd_sepol_mtime;
+       __s64           sdd_sepol_mtime;
        __u16           sdd_sepol_len;
        char            sdd_sepol[0];
 };