aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/rtnetlink.c23
-rw-r--r--net/decnet/netfilter/dn_rtmsg.c3
-rw-r--r--net/ipv4/netfilter/ip_queue.c20
-rw-r--r--net/ipv4/tcp_diag.c3
-rw-r--r--net/ipv6/netfilter/ip6_queue.c20
-rw-r--r--net/xfrm/xfrm_user.c15
6 files changed, 47 insertions, 37 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] =
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index f86a6259fd1..101ddef9ba9 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -119,8 +119,9 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
static void dnrmg_receive_user_sk(struct sock *sk, int len)
{
struct sk_buff *skb;
+ unsigned int 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))) {
dnrmg_receive_user_skb(skb);
kfree_skb(skb);
}
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 9e40dffc204..e5746b67441 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -546,20 +546,18 @@ ipq_rcv_skb(struct sk_buff *skb)
static void
ipq_rcv_sk(struct sock *sk, int len)
{
- do {
- struct sk_buff *skb;
+ struct sk_buff *skb;
+ unsigned int qlen;
- if (down_trylock(&ipqnl_sem))
- return;
+ down(&ipqnl_sem);
- while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
- ipq_rcv_skb(skb);
- kfree_skb(skb);
- }
+ for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
+ skb = skb_dequeue(&sk->sk_receive_queue);
+ ipq_rcv_skb(skb);
+ kfree_skb(skb);
+ }
- up(&ipqnl_sem);
-
- } while (ipqnl && ipqnl->sk_receive_queue.qlen);
+ up(&ipqnl_sem);
}
static int
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index 313c1408da3..8faa8948f75 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -777,8 +777,9 @@ static inline void tcpdiag_rcv_skb(struct sk_buff *skb)
static void tcpdiag_rcv(struct sock *sk, int len)
{
struct sk_buff *skb;
+ unsigned int 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))) {
tcpdiag_rcv_skb(skb);
kfree_skb(skb);
}
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index c54830b8959..750943e2d34 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -549,20 +549,18 @@ ipq_rcv_skb(struct sk_buff *skb)
static void
ipq_rcv_sk(struct sock *sk, int len)
{
- do {
- struct sk_buff *skb;
+ struct sk_buff *skb;
+ unsigned int qlen;
- if (down_trylock(&ipqnl_sem))
- return;
+ down(&ipqnl_sem);
- while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
- ipq_rcv_skb(skb);
- kfree_skb(skb);
- }
+ for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
+ skb = skb_dequeue(&sk->sk_receive_queue);
+ ipq_rcv_skb(skb);
+ kfree_skb(skb);
+ }
- up(&ipqnl_sem);
-
- } while (ipqnl && ipqnl->sk_receive_queue.qlen);
+ up(&ipqnl_sem);
}
static int
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 52b5843937c..dab112f1dd8 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1008,17 +1008,24 @@ static int xfrm_user_rcv_skb(struct sk_buff *skb)
static void xfrm_netlink_rcv(struct sock *sk, int len)
{
+ unsigned int qlen = skb_queue_len(&sk->sk_receive_queue);
+
do {
struct sk_buff *skb;
down(&xfrm_cfg_sem);
- while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ if (qlen > skb_queue_len(&sk->sk_receive_queue))
+ qlen = skb_queue_len(&sk->sk_receive_queue);
+
+ while (qlen--) {
+ skb = skb_dequeue(&sk->sk_receive_queue);
if (xfrm_user_rcv_skb(skb)) {
- if (skb->len)
+ if (skb->len) {
skb_queue_head(&sk->sk_receive_queue,
skb);
- else
+ qlen++;
+ } else
kfree_skb(skb);
break;
}
@@ -1027,7 +1034,7 @@ static void xfrm_netlink_rcv(struct sock *sk, int len)
up(&xfrm_cfg_sem);
- } while (xfrm_nl && xfrm_nl->sk_receive_queue.qlen);
+ } while (qlen);
}
static int build_expire(struct sk_buff *skb, struct xfrm_state *x, int hard)