summaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 5fb70cfa108..6e1ab1e34b2 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -609,26 +609,31 @@ static inline int rtnetlink_rcv_skb(struct sk_buff *skb)
/*
* rtnetlink input queue processing routine:
- * - try to acquire shared lock. If it is failed, defer processing.
+ * - process as much as there was in the queue upon entry.
* - feed skbs to rtnetlink_rcv_skb, until it refuse a message,
- * that will occur, when a dump started and/or acquisition of
- * exclusive lock failed.
+ * that will occur, when a dump started.
*/
static void rtnetlink_rcv(struct sock *sk, int len)
{
+ unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
+
do {
struct sk_buff *skb;
- if (rtnl_shlock_nowait())
- return;
+ rtnl_lock();
+
+ if (qlen > skb_queue_len(&sk->sk_receive_queue))
+ qlen = skb_queue_len(&sk->sk_receive_queue);
- while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ while (qlen--) {
+ skb = skb_dequeue(&sk->sk_receive_queue);
if (rtnetlink_rcv_skb(skb)) {
- if (skb->len)
+ if (skb->len) {
skb_queue_head(&sk->sk_receive_queue,
skb);
- else
+ qlen++;
+ } else
kfree_skb(skb);
break;
}
@@ -638,7 +643,7 @@ static void rtnetlink_rcv(struct sock *sk, int len)
up(&rtnl_sem);
netdev_run_todo();
- } while (rtnl && rtnl->sk_receive_queue.qlen);
+ } while (qlen);
}
static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =