commit 1eadec60573240c2b6ee3ce942471b3e0656e4dc Author: Patrick McHardy Date: Thu Sep 8 16:26:27 2011 +0200 netlink: improve flow control and speed up dumps with memory mapped I/O Improve dump flow control with memory mapped I/O: dumps are only continued if at least half the ring is free, similar to regular I/O. This minimizes the risk of receiving socket errors when the socket is also used for receiving regular unicast messages. Additionally speed up dumps by dumping multiple messages at once until the dump is either complete or less than half the ring is free. Signed-off-by: Patrick McHardy diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 2f4745d..fadf216 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -530,6 +530,24 @@ static void netlink_forward_ring(struct netlink_ring *ring) } while (ring->head != head); } +static bool netlink_dump_space(struct netlink_sock *nlk) +{ + struct netlink_ring *ring = &nlk->rx_ring; + struct nl_mmap_hdr *hdr; + unsigned int n; + + hdr = netlink_current_frame(ring, NL_MMAP_STATUS_UNUSED); + if (hdr == NULL) + return false; + + n = ring->head + ring->frame_max / 2; + if (n > ring->frame_max) + n -= ring->frame_max; + hdr = __netlink_lookup_frame(ring, n); + + return hdr->nm_status == NL_MMAP_STATUS_UNUSED; +} + static unsigned int netlink_poll(struct file *file, struct socket *sock, poll_table *wait) { @@ -543,11 +561,12 @@ static unsigned int netlink_poll(struct file *file, struct socket *sock, * is performed here under the assumption that the entire ring * has been processed before invoking poll(). */ - if (nlk->cb != NULL) { + while (nlk->cb != NULL && netlink_dump_space(nlk)) { err = netlink_dump(sk); if (err < 0) { sk->sk_err = err; sk->sk_error_report(sk); + break; } } netlink_rcv_wake(sk);