diff options
-rw-r--r-- | sys/kern/uipc_socket.c | 44 | ||||
-rw-r--r-- | sys/kern/uipc_socket2.c | 17 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 10 | ||||
-rw-r--r-- | sys/nfs/nfs_socket.c | 11 | ||||
-rw-r--r-- | sys/nfs/nfs_syscalls.c | 6 | ||||
-rw-r--r-- | sys/sys/socketvar.h | 6 | ||||
-rw-r--r-- | sys/sys/time.h | 19 |
7 files changed, 72 insertions, 41 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 58d78fbd5d4..7d497af7426 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.238 2019/12/31 13:48:32 visa Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.239 2020/01/15 13:17:35 mpi Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -155,6 +155,8 @@ socreate(int dom, struct socket **aso, int type, int proto) 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; } @@ -1113,6 +1124,7 @@ sorflush(struct socket *so) aso.so_rcv = *sb; memset(&sb->sb_startzero, 0, (caddr_t)&sb->sb_endzero - (caddr_t)&sb->sb_startzero); + sb->sb_timeo_nsecs = INFSLP; if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) (*pr->pr_domain->dom_dispose)(aso.so_rcv.sb_mb); sbrelease(&aso, &aso.so_rcv); @@ -1761,22 +1773,25 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m) 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 +1925,14 @@ sogetopt(struct socket *so, int level, int optname, struct mbuf *m) 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 +2145,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 diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 41bd63b1269..9c2492f39a5 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket2.c,v 1.101 2019/04/16 13:15:32 yasuoka Exp $ */ +/* $OpenBSD: uipc_socket2.c,v 1.102 2020/01/15 13:17:35 mpi Exp $ */ /* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */ /* @@ -181,10 +181,10 @@ sonewconn(struct socket *head, int connstatus) } 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 *sb) 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 *sb, int wait) 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); } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index e3956948a27..e3661b5f16c 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_syscalls.c,v 1.183 2020/01/05 13:46:02 visa Exp $ */ +/* $OpenBSD: uipc_syscalls.c,v 1.184 2020/01/15 13:17:35 mpi Exp $ */ /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ /* @@ -285,8 +285,8 @@ doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen, 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, register_t *retval) 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; diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c index 54d6e2a0d36..7648f35efff 100644 --- a/sys/nfs/nfs_socket.c +++ b/sys/nfs/nfs_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_socket.c,v 1.134 2019/12/05 10:41:57 mpi Exp $ */ +/* $OpenBSD: nfs_socket.c,v 1.135 2020/01/15 13:17:35 mpi Exp $ */ /* $NetBSD: nfs_socket.c,v 1.27 1996/04/15 20:20:00 thorpej Exp $ */ /* @@ -315,7 +315,8 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep) * 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 nfsreq *rep) * 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) + diff --git a/sys/nfs/nfs_syscalls.c b/sys/nfs/nfs_syscalls.c index 4a5a30c13df..637ef9d6dc3 100644 --- a/sys/nfs/nfs_syscalls.c +++ b/sys/nfs/nfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_syscalls.c,v 1.115 2019/12/05 10:41:57 mpi Exp $ */ +/* $OpenBSD: nfs_syscalls.c,v 1.116 2020/01/15 13:17:35 mpi Exp $ */ /* $NetBSD: nfs_syscalls.c,v 1.19 1996/02/18 11:53:52 fvdl Exp $ */ /* @@ -276,9 +276,9 @@ nfssvc_addsock(struct file *fp, struct mbuf *mynam) 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; diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 8ba05a13a5a..abcf20ed54d 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: socketvar.h,v 1.90 2019/12/12 16:33:02 visa Exp $ */ +/* $OpenBSD: socketvar.h,v 1.91 2020/01/15 13:17:35 mpi Exp $ */ /* $NetBSD: socketvar.h,v 1.18 1996/02/09 18:25:38 christos Exp $ */ /*- @@ -110,11 +110,11 @@ 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 */ short sb_flags; /* flags, see below */ /* End area that is zeroed on flush. */ #define sb_endzero sb_flags int sb_flagsintr; /* flags, changed atomically */ + uint64_t sb_timeo_nsecs;/* timeout for read/write */ struct selinfo sb_sel; /* process selecting read/write */ } so_rcv, so_snd; #define SB_MAX (2*1024*1024) /* default for max chars in sockbuf */ @@ -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); diff --git a/sys/sys/time.h b/sys/sys/time.h index faa25eb7e2a..564bae30b48 100644 --- a/sys/sys/time.h +++ b/sys/sys/time.h @@ -1,4 +1,4 @@ -/* $OpenBSD: time.h,v 1.49 2020/01/14 08:52:18 mpi Exp $ */ +/* $OpenBSD: time.h,v 1.50 2020/01/15 13:17:35 mpi Exp $ */ /* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */ /* @@ -332,6 +332,8 @@ void clock_secs_to_ymdhms(time_t, struct clock_ymdhms *); /* 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 timeval *tv) 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 timespec *ts) ts->tv_nsec = ns % 1000000000L; } -#include <sys/stdint.h> - static inline uint64_t SEC_TO_NSEC(uint64_t seconds) { |