netdev
[Top] [All Lists]

Re: [PATCH] netlink: defer socket destruction a bit

To: herbert@xxxxxxxxxxxxxxxxxxx
Subject: Re: [PATCH] netlink: defer socket destruction a bit
From: "David S. Miller" <davem@xxxxxxxxxxxxx>
Date: Thu, 19 May 2005 13:08:59 -0700 (PDT)
Cc: tommy.christensen@xxxxxxxxx, netdev@xxxxxxxxxxx, chamas@xxxxxxxxxxxxx
In-reply-to: <20050512103639.GA25631@gondor.apana.org.au>
References: <20050511230309.GA21547@gondor.apana.org.au> <1115891821.30106.86.camel@tsc-6.cph.tpack.net> <20050512103639.GA25631@gondor.apana.org.au>
Sender: netdev-bounce@xxxxxxxxxxx
From: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 12 May 2005 20:36:39 +1000

> On Thu, May 12, 2005 at 11:57:01AM +0200, Tommy Christensen wrote:
> > 
> > I moved the call to skb_orphan in the other patch, as you
> > suggested.  I think that also makes this patch safe as it is.
> > 
> > Right?
> 
> Indeed it is.  This also means that we don't hold onto the skb's
> share of rmalloc quota for an excessive amount of time if the
> number of broadcast sockets is large.

Ok, I think I got all the patches straight.  All of Tommy's
patches combined together look like this diff in my tree.
Please double check it.

Thanks.

diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -735,11 +735,15 @@ static inline int do_one_broadcast(struc
 
        sock_hold(sk);
        if (p->skb2 == NULL) {
-               if (atomic_read(&p->skb->users) != 1) {
+               if (skb_shared(p->skb)) {
                        p->skb2 = skb_clone(p->skb, p->allocation);
                } else {
-                       p->skb2 = p->skb;
-                       atomic_inc(&p->skb->users);
+                       p->skb2 = skb_get(p->skb);
+                       /*
+                        * skb ownership may have been set when
+                        * delivered to a previous socket.
+                        */
+                       skb_orphan(p->skb2);
                }
        }
        if (p->skb2 == NULL) {
@@ -785,11 +789,12 @@ int netlink_broadcast(struct sock *ssk, 
        sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
                do_one_broadcast(sk, &info);
 
+       kfree_skb(skb);
+
        netlink_unlock_table();
 
        if (info.skb2)
                kfree_skb(info.skb2);
-       kfree_skb(skb);
 
        if (info.delivered) {
                if (info.congested && (allocation & __GFP_WAIT))

<Prev in Thread] Current Thread [Next in Thread>