In udp_append() and udp_input(), make use of read locking on incpbs

rather than write locking: while we need to maintain a valid reference
to the inpcb and fix its state, no protocol layer state is modified
during an IPv4 UDP receive -- there are only changes at the socket
layer, which is separately protected by socket locking.

While parallel concurrent receive on a single UDP socket is currently
relatively unusual, introducing read locking in the transmit path,
allowing concurrent receive and transmit, will significantly improve
performance for loads such as BIND, memcached, etc.

MFC after:	2 months
Tested by:	gnn, kris, ps
This commit is contained in:
Robert Watson 2008-06-30 18:26:43 +00:00
parent 0889440a08
commit 119d85f6e0

View File

@ -195,7 +195,7 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off,
struct sockaddr_in6 udp_in6;
#endif
INP_WLOCK_ASSERT(inp);
INP_RLOCK_ASSERT(inp);
#ifdef IPSEC
/* Check AH/ESP integrity. */
@ -407,7 +407,7 @@ udp_input(struct mbuf *m, int off)
inp->inp_fport != uh->uh_sport)
continue;
INP_WLOCK(inp);
INP_RLOCK(inp);
/*
* Handle socket delivery policy for any-source
@ -464,7 +464,7 @@ udp_input(struct mbuf *m, int off)
}
}
if (blocked != 0) {
INP_WUNLOCK(inp);
INP_RUNLOCK(inp);
continue;
}
}
@ -475,7 +475,7 @@ udp_input(struct mbuf *m, int off)
if (n != NULL)
udp_append(last, ip, n, iphlen +
sizeof(struct udphdr), &udp_in);
INP_WUNLOCK(last);
INP_RUNLOCK(last);
}
last = inp;
/*
@ -502,7 +502,7 @@ udp_input(struct mbuf *m, int off)
}
udp_append(last, ip, m, iphlen + sizeof(struct udphdr),
&udp_in);
INP_WUNLOCK(last);
INP_RUNLOCK(last);
INP_INFO_RUNLOCK(&udbinfo);
return;
}
@ -541,17 +541,17 @@ udp_input(struct mbuf *m, int off)
/*
* Check the minimum TTL for socket.
*/
INP_WLOCK(inp);
INP_RLOCK(inp);
if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl)
goto badheadlocked;
udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in);
INP_WUNLOCK(inp);
INP_RUNLOCK(inp);
INP_INFO_RUNLOCK(&udbinfo);
return;
badheadlocked:
if (inp)
INP_WUNLOCK(inp);
INP_RUNLOCK(inp);
INP_INFO_RUNLOCK(&udbinfo);
badunlocked:
m_freem(m);