diff options
author | cheloha <cheloha@cvs.openbsd.org> | 2020-05-13 21:34:38 +0000 |
---|---|---|
committer | cheloha <cheloha@cvs.openbsd.org> | 2020-05-13 21:34:38 +0000 |
commit | e4fb65e66ab77bc59b2f2fe3776db770c2e66c52 (patch) | |
tree | 57b8cb7c728b7d0b0797d17d37d4403e2669d1ef | |
parent | 74593da698c1818da03ce6340f218a99488f3036 (diff) |
bpf(4): separate descriptor non-blocking status from read timeout
If you set FIONBIO on a bpf(4) descriptor you enable non-blocking mode
and also clobber any read timeout set for the descriptor. The reverse
is also true: do BIOCSRTIMEOUT and you'll set a timeout and
simultaneously disable non-blocking status. The two are mutually
exclusive.
This relationship is undocumented and might cause a bug. At the
very least it makes reasoning about the code difficult.
This patch adds a new member to bpf_d, bd_rnonblock, to store the
non-blocking status of the descriptor. The read timeout is still
kept in bd_rtout.
With this in place, non-blocking status and the read timeout can
coexist. Setting one state does not clear the other, and vice versa.
Separating the two states also clears the way for changing the bpf(4)
read timeout to use the system clock instead of ticks. More on that
in a later patch.
With insight from dlg@ regarding the purpose of the read timeout.
ok dlg@
-rw-r--r-- | sys/net/bpf.c | 18 | ||||
-rw-r--r-- | sys/net/bpfdesc.h | 3 |
2 files changed, 11 insertions, 10 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c index fd35b5e2b04..f2a4972af9f 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf.c,v 1.189 2020/04/07 13:27:52 visa Exp $ */ +/* $OpenBSD: bpf.c,v 1.190 2020/05/13 21:34:37 cheloha Exp $ */ /* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */ /* @@ -379,8 +379,8 @@ bpfopen(dev_t dev, int flag, int mode, struct proc *p) smr_init(&bd->bd_smr); sigio_init(&bd->bd_sigio); - if (flag & FNONBLOCK) - bd->bd_rtout = -1; + bd->bd_rtout = 0; /* no timeout by default */ + bd->bd_rnonblock = ISSET(flag, FNONBLOCK); bpf_get(bd); LIST_INSERT_HEAD(&bpf_d_list, bd, bd_list); @@ -453,7 +453,7 @@ bpfread(dev_t dev, struct uio *uio, int ioflag) * If there's a timeout, bd_rdStart is tagged when we start the read. * we can then figure out when we're done reading. */ - if (d->bd_rtout != -1 && d->bd_rdStart == 0) + if (d->bd_rnonblock == 0 && d->bd_rdStart == 0) d->bd_rdStart = ticks; else d->bd_rdStart = 0; @@ -482,7 +482,7 @@ bpfread(dev_t dev, struct uio *uio, int ioflag) ROTATE_BUFFERS(d); break; } - if (d->bd_rtout == -1) { + if (d->bd_rnonblock) { /* User requested non-blocking I/O */ error = EWOULDBLOCK; } else { @@ -960,9 +960,9 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) case FIONBIO: /* Non-blocking I/O */ if (*(int *)addr) - d->bd_rtout = -1; + d->bd_rnonblock = 1; else - d->bd_rtout = 0; + d->bd_rnonblock = 0; break; case FIOASYNC: /* Send signal on receive packets */ @@ -1153,7 +1153,7 @@ bpfpoll(dev_t dev, int events, struct proc *p) * if there's a timeout, mark the time we * started waiting. */ - if (d->bd_rtout != -1 && d->bd_rdStart == 0) + if (d->bd_rnonblock == 0 && d->bd_rdStart == 0) d->bd_rdStart = ticks; selrecord(p, &d->bd_sel); } @@ -1193,7 +1193,7 @@ bpfkqfilter(dev_t dev, struct knote *kn) klist_insert(klist, kn); mtx_enter(&d->bd_mtx); - if (d->bd_rtout != -1 && d->bd_rdStart == 0) + if (d->bd_rnonblock == 0 && d->bd_rdStart == 0) d->bd_rdStart = ticks; mtx_leave(&d->bd_mtx); diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h index 41b65116b41..330b091b9db 100644 --- a/sys/net/bpfdesc.h +++ b/sys/net/bpfdesc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bpfdesc.h,v 1.40 2020/01/02 16:23:01 claudio Exp $ */ +/* $OpenBSD: bpfdesc.h,v 1.41 2020/05/13 21:34:37 cheloha Exp $ */ /* $NetBSD: bpfdesc.h,v 1.11 1995/09/27 18:30:42 thorpej Exp $ */ /* @@ -74,6 +74,7 @@ struct bpf_d { struct bpf_if *bd_bif; /* interface descriptor */ u_long bd_rtout; /* Read timeout in 'ticks' */ u_long bd_rdStart; /* when the read started */ + int bd_rnonblock; /* true if nonblocking reads are set */ struct bpf_program_smr *bd_rfilter; /* read filter code */ struct bpf_program_smr |