Now that we have a mechanism to check when to lock the socket inside a
kqueue filter, let's use it.
Diff below protects `so_qlen', `so_state' and `so_snd.sb_lowat' which
are accessed in tcp_input().
ok?
Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.189
diff -u -p -r1.189 uipc_socket.c
--- kern/uipc_socket.c 26 Jun 2017 09:32:31 -0000 1.189
+++ kern/uipc_socket.c 26 Jun 2017 14:00:46 -0000
@@ -1991,35 +1991,44 @@ int
filt_sowrite(struct knote *kn, long hint)
{
struct socket *so = kn->kn_fp->f_data;
- int s;
+ int s, rv;
if (!(hint & NOTE_SUBMIT))
s = solock(so);
kn->kn_data = sbspace(so, &so->so_snd);
- if (!(hint & NOTE_SUBMIT))
- sounlock(s);
if (so->so_state & SS_CANTSENDMORE) {
kn->kn_flags |= EV_EOF;
kn->kn_fflags = so->so_error;
- return (1);
+ rv = 1;
+ } else if (so->so_error) { /* temporary udp error */
+ rv = 1;
+ } else if (((so->so_state & SS_ISCONNECTED) == 0) &&
+ (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
+ rv = 0;
+ } if (kn->kn_sfflags & NOTE_LOWAT) {
+ rv = (kn->kn_data >= kn->kn_sdata);
+ } else {
+ rv = (kn->kn_data >= so->so_snd.sb_lowat);
}
- if (so->so_error) /* temporary udp error */
- return (1);
- if (((so->so_state & SS_ISCONNECTED) == 0) &&
- (so->so_proto->pr_flags & PR_CONNREQUIRED))
- return (0);
- if (kn->kn_sfflags & NOTE_LOWAT)
- return (kn->kn_data >= kn->kn_sdata);
- return (kn->kn_data >= so->so_snd.sb_lowat);
+ if (!(hint & NOTE_SUBMIT))
+ sounlock(s);
+
+ return (rv);
}
int
filt_solisten(struct knote *kn, long hint)
{
struct socket *so = kn->kn_fp->f_data;
+ int s;
+ if (!(hint & NOTE_SUBMIT))
+ s = solock(so);
kn->kn_data = so->so_qlen;
- return (so->so_qlen != 0);
+ if (!(hint & NOTE_SUBMIT))
+ sounlock(s);
+
+ return (kn->kn_data != 0);
}
#ifdef DDB