summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/uipc_socket.c44
-rw-r--r--sys/kern/uipc_socket2.c17
-rw-r--r--sys/kern/uipc_syscalls.c10
-rw-r--r--sys/nfs/nfs_socket.c11
-rw-r--r--sys/nfs/nfs_syscalls.c6
-rw-r--r--sys/sys/socketvar.h6
-rw-r--r--sys/sys/time.h19
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)
{