===== net/netlink/af_netlink.c 1.56 vs edited ===== --- 1.56/net/netlink/af_netlink.c 2004-09-29 07:47:22 +10:00 +++ edited/net/netlink/af_netlink.c 2004-10-16 21:23:29 +10:00 @@ -593,7 +593,7 @@ skb_set_owner_r(skb, sk); skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk, skb->len); - return 0; + return atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf; } return -1; } @@ -606,6 +606,8 @@ struct sk_buff *skb2 = NULL; int protocol = ssk->sk_protocol; int failure = 0, delivered = 0; + int congested = 0; + int val; netlink_trim(skb, allocation); @@ -640,9 +642,10 @@ netlink_overrun(sk); /* Clone failed. Notify ALL listeners. */ failure = 1; - } else if (netlink_broadcast_deliver(sk, skb2)) { + } else if ((val = netlink_broadcast_deliver(sk, skb2)) < 0) { netlink_overrun(sk); } else { + congested |= val; delivered = 1; skb2 = NULL; } @@ -655,8 +658,11 @@ kfree_skb(skb2); kfree_skb(skb); - if (delivered) + if (delivered) { + if (congested && (allocation & __GFP_WAIT)) + yield(); return 0; + } if (failure) return -ENOBUFS; return -ESRCH;