When we converted most of the splsoftnet() to NET_LOCK() we ended up
with some "lock" inversions between the socket buffer "lock" and the
NET_LOCK(). At that time the KERNEL_LOCK() was serializing access to
`sb_flags'.
We're now moving towards running sockets functions w/o KERNEL_LOCK()
in protocol input paths. So I'd like to assert that the socket lock
is held when sb_flags are modified.
There's currently one exception to this rule, FIFO kqueue filters,
that I'll address in a later diff.
ok?
Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.207
diff -u -p -r1.207 uipc_socket.c
--- kern/uipc_socket.c 4 Nov 2017 14:13:53 -0000 1.207
+++ kern/uipc_socket.c 22 Nov 2017 11:22:02 -0000
@@ -453,7 +453,7 @@ restart:
(atomic || space < so->so_snd.sb_lowat))) {
if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT))
snderr(EWOULDBLOCK);
- sbunlock(&so->so_snd);
+ sbunlock(so, &so->so_snd);
error = sbwait(so, &so->so_snd);
so->so_state &= ~SS_ISSENDING;
if (error)
@@ -497,7 +497,7 @@ restart:
release:
so->so_state &= ~SS_ISSENDING;
- sbunlock(&so->so_snd);
+ sbunlock(so, &so->so_snd);
out:
sounlock(s);
m_freem(top);
@@ -736,7 +736,7 @@ restart:
}
SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1");
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1");
- sbunlock(&so->so_rcv);
+ sbunlock(so, &so->so_rcv);
error = sbwait(so, &so->so_rcv);
sounlock(s);
if (error)
@@ -957,7 +957,7 @@ dontblock:
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2");
error = sbwait(so, &so->so_rcv);
if (error) {
- sbunlock(&so->so_rcv);
+ sbunlock(so, &so->so_rcv);
sounlock(s);
return (0);
}
@@ -993,7 +993,7 @@ dontblock:
}
if (orig_resid == uio->uio_resid && orig_resid &&
(flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
- sbunlock(&so->so_rcv);
+ sbunlock(so, &so->so_rcv);
sounlock(s);
goto restart;
}
@@ -1004,7 +1004,7 @@ dontblock:
if (flagsp)
*flagsp |= flags;
release:
- sbunlock(&so->so_rcv);
+ sbunlock(so, &so->so_rcv);
sounlock(s);
return (error);
}
@@ -1049,7 +1049,7 @@ sorflush(struct socket *so)
/* with SB_NOINTR and M_WAITOK sblock() must not fail */
KASSERT(error == 0);
socantrcvmore(so);
- sbunlock(sb);
+ sbunlock(so, sb);
aso.so_proto = pr;
aso.so_rcv = *sb;
memset(sb, 0, sizeof (*sb));
@@ -1110,7 +1110,7 @@ sosplice(struct socket *so, int fd, off_
}
if (so->so_sp->ssp_socket)
sounsplice(so, so->so_sp->ssp_socket, 1);
- sbunlock(&so->so_rcv);
+ sbunlock(so, &so->so_rcv);
return (0);
}
@@ -1139,7 +1139,7 @@ sosplice(struct socket *so, int fd, off_
return (error);
}
if ((error = sblock(so, &sosp->so_snd, M_WAITOK)) != 0) {
- sbunlock(&so->so_rcv);
+ sbunlock(so, &so->so_rcv);
FRELE(fp, curproc);
return (error);
}
@@ -1183,8 +1183,8 @@ sosplice(struct socket *so, int fd, off_
}
release:
- sbunlock(&sosp->so_snd);
- sbunlock(&so->so_rcv);
+ sbunlock(sosp, &sosp->so_snd);
+ sbunlock(so, &so->so_rcv);
FRELE(fp, curproc);
return (error);
}
Index: kern/uipc_socket2.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket2.c,v
retrieving revision 1.86
diff -u -p -r1.86 uipc_socket2.c
--- kern/uipc_socket2.c 11 Aug 2017 21:24:19 -0000 1.86
+++ kern/uipc_socket2.c 22 Nov 2017 11:22:37 -0000
@@ -342,7 +342,6 @@ sblock(struct socket *so, struct sockbuf
{
int error, prio = (sb->sb_flags & SB_NOINTR) ? PSOCK : PSOCK | PCATCH;
- KERNEL_ASSERT_LOCKED();
soassertlocked(so);
if ((sb->sb_flags & SB_LOCK) == 0) {
@@ -363,9 +362,9 @@ sblock(struct socket *so, struct sockbuf
}
void
-sbunlock(struct sockbuf *sb)
+sbunlock(struct socket *so, struct sockbuf *sb)
{
- KERNEL_ASSERT_LOCKED();
+ soassertlocked(so);
sb->sb_flags &= ~SB_LOCK;
if (sb->sb_flags & SB_WANT) {
Index: sys/socketvar.h
===================================================================
RCS file: /cvs/src/sys/sys/socketvar.h,v
retrieving revision 1.77
diff -u -p -r1.77 socketvar.h
--- sys/socketvar.h 4 Nov 2017 14:13:53 -0000 1.77
+++ sys/socketvar.h 22 Nov 2017 11:22:49 -0000
@@ -244,7 +244,7 @@ soreadable(struct socket *so)
int sblock(struct socket *, struct sockbuf *, int);
/* release lock on sockbuf sb */
-void sbunlock(struct sockbuf *);
+void sbunlock(struct socket *, struct sockbuf *);
#define SB_EMPTY_FIXUP(sb) do {
\
if ((sb)->sb_mb == NULL) { \