netdev
[Top] [All Lists]

assertion (!atomic_read(&sk->sk_rmem_alloc)) failed at net/netlink/af_ne

To: netdev@xxxxxxxxxxx
Subject: assertion (!atomic_read(&sk->sk_rmem_alloc)) failed at net/netlink/af_netlink.c (122)
From: Ken-ichirou MATSUZAWA <chamas@xxxxxxxxxxxxx>
Date: Tue, 10 May 2005 21:43:32 +0900 (JST)
Sender: netdev-bounce@xxxxxxxxxxx
 Hello.

Everytime on shutting down, the subject message is logged.  
It seems that the reason is do_one_broadcast may preempt
netlink_recvmsg. Added patch to 2.6.12-rc4 seems resolving this
problem.

But I'm not a kernel hacker. I don't understand design, detail and
the intenstion of struct netlink_broadcast_data, so that I hope
someone to do more tidy work. In addition, please check 2.4 kernel
and pfkey_broadcast_one too.

Thanks.

--- net/netlink/af_netlink.c.orig       2005-05-10 21:03:11.000000000 +0900
+++ net/netlink/af_netlink.c    2005-05-10 21:10:39.000000000 +0900
@@ -721,7 +721,7 @@
        int congested;
        int delivered;
        int allocation;
-       struct sk_buff *skb, *skb2;
+       struct sk_buff *skb;
 };
 
 static inline int do_one_broadcast(struct sock *sk,
@@ -729,6 +729,7 @@
 {
        struct netlink_sock *nlk = nlk_sk(sk);
        int val;
+       struct sk_buff *skb;
 
        if (p->exclude_sk == sk)
                goto out;
@@ -741,25 +742,21 @@
                goto out;
        }
 
-       sock_hold(sk);
-       if (p->skb2 == NULL) {
-               if (atomic_read(&p->skb->users) != 1) {
-                       p->skb2 = skb_clone(p->skb, p->allocation);
-               } else {
-                       p->skb2 = p->skb;
-                       atomic_inc(&p->skb->users);
-               }
-       }
-       if (p->skb2 == NULL) {
+       skb = skb_clone(p->skb, p->allocation);
+       if (skb == NULL) {
                netlink_overrun(sk);
                /* Clone failed. Notify ALL listeners. */
                p->failure = 1;
-       } else if ((val = netlink_broadcast_deliver(sk, p->skb2)) < 0) {
+               goto out;
+       }
+
+       sock_hold(sk);
+       if ((val = netlink_broadcast_deliver(sk, skb)) < 0) {
                netlink_overrun(sk);
+               kfree_skb(skb);
        } else {
                p->congested |= val;
                p->delivered = 1;
-               p->skb2 = NULL;
        }
        sock_put(sk);
 
@@ -784,7 +781,6 @@
        info.delivered = 0;
        info.allocation = allocation;
        info.skb = skb;
-       info.skb2 = NULL;
 
        /* While we sleep in clone, do not allow to change socket list */
 
@@ -795,8 +791,6 @@
 
        netlink_unlock_table();
 
-       if (info.skb2)
-               kfree_skb(info.skb2);
        kfree_skb(skb);
 
        if (info.delivered) {
<Prev in Thread] Current Thread [Next in Thread>