netdev
[Top] [All Lists]

Re: [PATCH] Move inetdev/ifa over to RCU

To: Stephen Hemminger <shemminger@xxxxxxxx>
Subject: Re: [PATCH] Move inetdev/ifa over to RCU
From: "David S. Miller" <davem@xxxxxxxxxx>
Date: Fri, 13 Aug 2004 09:38:38 -0700
Cc: netdev@xxxxxxxxxxx, herbert@xxxxxxxxxxxxxxxxxxx
In-reply-to: <20040813090314.448c971d@dell_ss3.pdx.osdl.net>
References: <20040812165954.00429e65.davem@redhat.com> <20040813090314.448c971d@dell_ss3.pdx.osdl.net>
Sender: netdev-bounce@xxxxxxxxxxx
Thanks guys.  This patch should fix both problems.

Herbert, if we check inetdev->dead when trying to grab
a reference it fixes the RCU destroy race you mentioned.
I really don't want to put that ref drop into the
RCU callback as that would kill performance.

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/08/13 09:17:07-07:00 davem@xxxxxxxxxxxxxxxxxx 
#   [IPV4]: Fix two bugs in inetdev RCU handling.
#   
#   - Two missing smp_read_barrier_depends() noticed by
#     Stephen Hemminger.
#   - Fix RCU inetdev destroy race spotted by Herbert Xu.
#     Check in_dev->dead when trying to grab a reference.
#   
#   Signed-off-by: David S. Miller <davem@xxxxxxxxxx>
# 
# net/ipv4/devinet.c
#   2004/08/13 09:15:41-07:00 davem@xxxxxxxxxxxxxxxxxx +1 -0
#   [IPV4]: Fix two bugs in inetdev RCU handling.
# 
# include/linux/inetdevice.h
#   2004/08/13 09:15:41-07:00 davem@xxxxxxxxxxxxxxxxxx +7 -2
#   [IPV4]: Fix two bugs in inetdev RCU handling.
# 
diff -Nru a/include/linux/inetdevice.h b/include/linux/inetdevice.h
--- a/include/linux/inetdevice.h        2004-08-13 09:20:01 -07:00
+++ b/include/linux/inetdevice.h        2004-08-13 09:20:01 -07:00
@@ -143,9 +143,14 @@
        struct in_device *in_dev;
 
        rcu_read_lock();
+       smp_read_barrier_depends();
        in_dev = dev->ip_ptr;
-       if (in_dev)
-               atomic_inc(&in_dev->refcnt);
+       if (in_dev) {
+               if (in_dev->dead)
+                       in_dev = NULL;
+               else
+                       atomic_inc(&in_dev->refcnt);
+       }
        rcu_read_unlock();
        return in_dev;
 }
diff -Nru a/net/ipv4/devinet.c b/net/ipv4/devinet.c
--- a/net/ipv4/devinet.c        2004-08-13 09:20:01 -07:00
+++ b/net/ipv4/devinet.c        2004-08-13 09:20:01 -07:00
@@ -210,6 +210,7 @@
 int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
 {
        rcu_read_lock();
+       smp_read_barrier_depends();
        for_primary_ifa(in_dev) {
                if (inet_ifa_match(a, ifa)) {
                        if (!b || inet_ifa_match(b, ifa)) {

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