On 13/01/20(Mon) 12:27, Martin Pieuchot wrote:
> On 13/01/20(Mon) 12:16, Alexander Bluhm wrote:
> > On Sun, Jan 12, 2020 at 01:33:43PM +0100, Martin Pieuchot wrote:
> > > @@ -304,7 +306,7 @@ soclose(struct socket *so, int flags)
> > >                   while (so->so_state & SS_ISCONNECTED) {
> > >                           error = sosleep(so, &so->so_timeo,
> > >                               PSOCK | PCATCH, "netcls",
> > > -                             so->so_linger * hz);
> > > +                             SEC_TO_NSEC(so->so_linger));
> > >                           if (error)
> > >                                   break;
> > >                   }
> > 
> > In sosleep() the sleep forever semantics has been converted from 0
> > to INFSLP.  We have to pay attention at every caller.
> 
> Fixed in the diff below.
> 
> > > @@ -333,11 +333,11 @@ nfs_connect(struct nfsmount *nmp, struct
> > 
> > In this function is a call that has been forgotten in the conversion.
> >                         sosleep(so, &so->so_timeo, PSOCK, "nfscon", 2 * hz);
> > 
> > Should we rename sosleep() to sosleep_nsec() and force to have all
> > the critical places in the diff?  Its semantics has changed, maybe
> > we should change the name.
> 
> I'm not fan of such churn, hopefully all tsleep(9) will be soon
> converted and there won't be a need for the "_nsec" suffix.

bluhm@ insisted on the _nsec naming, here's the diff.

Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.238
diff -u -p -r1.238 uipc_socket.c
--- kern/uipc_socket.c  31 Dec 2019 13:48:32 -0000      1.238
+++ kern/uipc_socket.c  13 Jan 2020 11:54:58 -0000
@@ -155,6 +155,8 @@ socreate(int dom, struct socket **aso, i
        so->so_egid = p->p_ucred->cr_gid;
        so->so_cpid = p->p_p->ps_pid;
        so->so_proto = prp;
+       so->so_snd.sb_timeo_nsecs = INFSLP;
+       so->so_rcv.sb_timeo_nsecs = INFSLP;
 
        s = solock(so);
        error = (*prp->pr_attach)(so, proto);
@@ -265,6 +267,15 @@ sofree(struct socket *so, int s)
        }
 }
 
+static inline uint64_t
+solinger_nsec(struct socket *so)
+{
+       if (so->so_linger == 0)
+               return INFSLP;
+
+       return SEC_TO_NSEC(so->so_linger);
+}
+
 /*
  * Close a socket on last file table reference removal.
  * Initiate disconnect if connected.
@@ -302,9 +313,9 @@ soclose(struct socket *so, int flags)
                            (flags & MSG_DONTWAIT))
                                goto drop;
                        while (so->so_state & SS_ISCONNECTED) {
-                               error = sosleep(so, &so->so_timeo,
+                               error = sosleep_nsec(so, &so->so_timeo,
                                    PSOCK | PCATCH, "netcls",
-                                   so->so_linger * hz);
+                                   solinger_nsec(so));
                                if (error)
                                        break;
                        }
@@ -1761,22 +1772,25 @@ sosetopt(struct socket *so, int level, i
                case SO_RCVTIMEO:
                    {
                        struct timeval tv;
-                       int val;
+                       uint64_t nsecs;
 
                        if (m == NULL || m->m_len < sizeof (tv))
                                return (EINVAL);
                        memcpy(&tv, mtod(m, struct timeval *), sizeof tv);
-                       val = tvtohz(&tv);
-                       if (val > USHRT_MAX)
+                       if (!timerisvalid(&tv))
+                               return (EINVAL);
+                       nsecs = TIMEVAL_TO_NSEC(&tv);
+                       if (nsecs == UINT64_MAX)
                                return (EDOM);
-
+                       if (nsecs == 0)
+                               nsecs = INFSLP;
                        switch (optname) {
 
                        case SO_SNDTIMEO:
-                               so->so_snd.sb_timeo = val;
+                               so->so_snd.sb_timeo_nsecs = nsecs;
                                break;
                        case SO_RCVTIMEO:
-                               so->so_rcv.sb_timeo = val;
+                               so->so_rcv.sb_timeo_nsecs = nsecs;
                                break;
                        }
                        break;
@@ -1910,13 +1924,14 @@ sogetopt(struct socket *so, int level, i
                case SO_RCVTIMEO:
                    {
                        struct timeval tv;
-                       int val = (optname == SO_SNDTIMEO ?
-                           so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
+                       uint64_t nsecs = (optname == SO_SNDTIMEO ?
+                           so->so_snd.sb_timeo_nsecs :
+                           so->so_rcv.sb_timeo_nsecs);
 
                        m->m_len = sizeof(struct timeval);
                        memset(&tv, 0, sizeof(tv));
-                       tv.tv_sec = val / hz;
-                       tv.tv_usec = (val % hz) * tick;
+                       if (nsecs != INFSLP)
+                               NSEC_TO_TIMEVAL(nsecs, &tv);
                        memcpy(mtod(m, struct timeval *), &tv, sizeof tv);
                        break;
                    }
@@ -2129,7 +2144,7 @@ sobuf_print(struct sockbuf *sb,
        (*pr)("\tsb_sel: ...\n");
        (*pr)("\tsb_flagsintr: %d\n", sb->sb_flagsintr);
        (*pr)("\tsb_flags: %i\n", sb->sb_flags);
-       (*pr)("\tsb_timeo: %i\n", sb->sb_timeo);
+       (*pr)("\tsb_timeo_nsecs: %llu\n", sb->sb_timeo_nsecs);
 }
 
 void
Index: kern/uipc_socket2.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket2.c,v
retrieving revision 1.101
diff -u -p -r1.101 uipc_socket2.c
--- kern/uipc_socket2.c 16 Apr 2019 13:15:32 -0000      1.101
+++ kern/uipc_socket2.c 13 Jan 2020 11:55:28 -0000
@@ -181,10 +181,10 @@ sonewconn(struct socket *head, int conns
        }
        so->so_snd.sb_wat = head->so_snd.sb_wat;
        so->so_snd.sb_lowat = head->so_snd.sb_lowat;
-       so->so_snd.sb_timeo = head->so_snd.sb_timeo;
+       so->so_snd.sb_timeo_nsecs = head->so_snd.sb_timeo_nsecs;
        so->so_rcv.sb_wat = head->so_rcv.sb_wat;
        so->so_rcv.sb_lowat = head->so_rcv.sb_lowat;
-       so->so_rcv.sb_timeo = head->so_rcv.sb_timeo;
+       so->so_rcv.sb_timeo_nsecs = head->so_rcv.sb_timeo_nsecs;
 
        sigio_init(&so->so_sigio);
        sigio_copy(&so->so_sigio, &head->so_sigio);
@@ -332,14 +332,15 @@ soassertlocked(struct socket *so)
 }
 
 int
-sosleep(struct socket *so, void *ident, int prio, const char *wmesg, int timo)
+sosleep_nsec(struct socket *so, void *ident, int prio, const char *wmesg,
+    uint64_t nsecs)
 {
        if ((so->so_proto->pr_domain->dom_family != PF_UNIX) &&
            (so->so_proto->pr_domain->dom_family != PF_ROUTE) &&
            (so->so_proto->pr_domain->dom_family != PF_KEY)) {
-               return rwsleep(ident, &netlock, prio, wmesg, timo);
+               return rwsleep_nsec(ident, &netlock, prio, wmesg, nsecs);
        } else
-               return tsleep(ident, prio, wmesg, timo);
+               return tsleep_nsec(ident, prio, wmesg, nsecs);
 }
 
 /*
@@ -353,7 +354,7 @@ sbwait(struct socket *so, struct sockbuf
        soassertlocked(so);
 
        sb->sb_flags |= SB_WAIT;
-       return (sosleep(so, &sb->sb_cc, prio, "netio", sb->sb_timeo));
+       return sosleep_nsec(so, &sb->sb_cc, prio, "netio", sb->sb_timeo_nsecs);
 }
 
 int
@@ -372,7 +373,7 @@ sblock(struct socket *so, struct sockbuf
 
        while (sb->sb_flags & SB_LOCK) {
                sb->sb_flags |= SB_WANT;
-               error = sosleep(so, &sb->sb_flags, prio, "netlck", 0);
+               error = sosleep_nsec(so, &sb->sb_flags, prio, "netlck", INFSLP);
                if (error)
                        return (error);
        }
Index: kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.183
diff -u -p -r1.183 uipc_syscalls.c
--- kern/uipc_syscalls.c        5 Jan 2020 13:46:02 -0000       1.183
+++ kern/uipc_syscalls.c        13 Jan 2020 11:55:50 -0000
@@ -285,8 +285,8 @@ doaccept(struct proc *p, int sock, struc
                        head->so_error = ECONNABORTED;
                        break;
                }
-               error = sosleep(head, &head->so_timeo, PSOCK | PCATCH, "netcon",
-                   0);
+               error = sosleep_nsec(head, &head->so_timeo, PSOCK | PCATCH,
+                   "netcon", INFSLP);
                if (error)
                        goto out;
        }
@@ -388,8 +388,8 @@ sys_connect(struct proc *p, void *v, reg
                goto out;
        }
        while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
-               error = sosleep(so, &so->so_timeo, PSOCK | PCATCH,
-                   "netcon2", 0);
+               error = sosleep_nsec(so, &so->so_timeo, PSOCK | PCATCH,
+                   "netcon2", INFSLP);
                if (error) {
                        if (error == EINTR || error == ERESTART)
                                interrupted = 1;
Index: nfs/nfs_socket.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_socket.c,v
retrieving revision 1.134
diff -u -p -r1.134 nfs_socket.c
--- nfs/nfs_socket.c    5 Dec 2019 10:41:57 -0000       1.134
+++ nfs/nfs_socket.c    13 Jan 2020 11:55:59 -0000
@@ -315,7 +315,8 @@ nfs_connect(struct nfsmount *nmp, struct
                 * that interruptible mounts don't hang here for a long time.
                 */
                while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
-                       sosleep(so, &so->so_timeo, PSOCK, "nfscon", 2 * hz);
+                       sosleep_nsec(so, &so->so_timeo, PSOCK, "nfscon",
+                           SEC_TO_NSEC(2));
                        if ((so->so_state & SS_ISCONNECTING) &&
                            so->so_error == 0 && rep &&
                            (error = nfs_sigintr(nmp, rep, rep->r_procp)) != 0){
@@ -333,11 +334,11 @@ nfs_connect(struct nfsmount *nmp, struct
         * Always set receive timeout to detect server crash and reconnect.
         * Otherwise, we can get stuck in soreceive forever.
         */
-       so->so_rcv.sb_timeo = (5 * hz);
+       so->so_rcv.sb_timeo_nsecs = SEC_TO_NSEC(5);
        if (nmp->nm_flag & (NFSMNT_SOFT | NFSMNT_INT))
-               so->so_snd.sb_timeo = (5 * hz);
+               so->so_snd.sb_timeo_nsecs = SEC_TO_NSEC(5);
        else
-               so->so_snd.sb_timeo = 0;
+               so->so_snd.sb_timeo_nsecs = INFSLP;
        if (nmp->nm_sotype == SOCK_DGRAM) {
                sndreserve = nmp->nm_wsize + NFS_MAXPKTHDR;
                rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
Index: nfs/nfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_syscalls.c,v
retrieving revision 1.115
diff -u -p -r1.115 nfs_syscalls.c
--- nfs/nfs_syscalls.c  5 Dec 2019 10:41:57 -0000       1.115
+++ nfs/nfs_syscalls.c  12 Jan 2020 12:19:47 -0000
@@ -276,9 +276,9 @@ nfssvc_addsock(struct file *fp, struct m
                m_freem(m);
        }
        so->so_rcv.sb_flags &= ~SB_NOINTR;
-       so->so_rcv.sb_timeo = 0;
+       so->so_rcv.sb_timeo_nsecs = INFSLP;
        so->so_snd.sb_flags &= ~SB_NOINTR;
-       so->so_snd.sb_timeo = 0;
+       so->so_snd.sb_timeo_nsecs = INFSLP;
        sounlock(so, s);
        if (tslp)
                slp = tslp;
Index: sys/socketvar.h
===================================================================
RCS file: /cvs/src/sys/sys/socketvar.h,v
retrieving revision 1.90
diff -u -p -r1.90 socketvar.h
--- sys/socketvar.h     12 Dec 2019 16:33:02 -0000      1.90
+++ sys/socketvar.h     13 Jan 2020 11:56:07 -0000
@@ -110,7 +110,7 @@ struct socket {
                struct mbuf *sb_mbtail; /* the last mbuf in the chain */
                struct mbuf *sb_lastrecord;/* first mbuf of last record in
                                              socket buffer */
-               u_short sb_timeo;       /* timeout for read/write */
+               uint64_t sb_timeo_nsecs;        /* timeout for read/write */
                short   sb_flags;       /* flags, see below */
 /* End area that is zeroed on flush. */
 #define        sb_endzero      sb_flags
@@ -338,7 +338,7 @@ void        sorwakeup(struct socket *);
 void   sowwakeup(struct socket *);
 int    sockargs(struct mbuf **, const void *, size_t, int);
 
-int    sosleep(struct socket *, void *, int, const char *, int);
+int    sosleep_nsec(struct socket *, void *, int, const char *, uint64_t);
 int    solock(struct socket *);
 void   sounlock(struct socket *, int);
 
Index: sys/time.h
===================================================================
RCS file: /cvs/src/sys/sys/time.h,v
retrieving revision 1.48
diff -u -p -r1.48 time.h
--- sys/time.h  1 Jan 2020 14:09:59 -0000       1.48
+++ sys/time.h  12 Jan 2020 12:21:33 -0000
@@ -332,6 +332,8 @@ void clock_secs_to_ymdhms(time_t, struct
 /* Traditional POSIX base year */
 #define POSIX_BASE_YEAR 1970
 
+#include <sys/stdint.h>
+
 static inline void
 NSEC_TO_TIMEVAL(uint64_t ns, struct timeval *tv)
 {
@@ -339,6 +341,19 @@ NSEC_TO_TIMEVAL(uint64_t ns, struct time
        tv->tv_usec = (ns % 1000000000L) / 1000;
 }
 
+static inline uint64_t
+TIMEVAL_TO_NSEC(const struct timeval *tv)
+{
+       uint64_t nsecs;
+
+       if (tv->tv_sec > UINT64_MAX / 1000000000ULL)
+               return UINT64_MAX;
+       nsecs = tv->tv_sec * 1000000000ULL;
+       if (tv->tv_usec * 1000ULL > UINT64_MAX - nsecs)
+               return UINT64_MAX;
+       return nsecs + tv->tv_usec * 1000ULL;
+}
+
 static inline void
 NSEC_TO_TIMESPEC(uint64_t ns, struct timespec *ts)
 {
@@ -346,8 +361,6 @@ NSEC_TO_TIMESPEC(uint64_t ns, struct tim
        ts->tv_nsec = ns % 1000000000L;
 }
 
-#include <sys/stdint.h>
-
 static inline uint64_t
 SEC_TO_NSEC(uint64_t seconds)
 {

Reply via email to