From: Rusty Russell <rusty@rustcorp.com.au>
To: "David S. Miller" <davem@redhat.com>
Cc: kuznet@ms2.inr.ac.ru
Cc: shemminger@osdl.org, netdev@oss.sgi.com, acme@conectiva.com.br,
Werner Almesberger <wa@almesberger.net>
Subject: Re: dev->destructor
Date: Thu, 01 May 2003 22:01:19 +1000 [thread overview]
Message-ID: <20030501120815.25BE22C155@lists.samba.org> (raw)
In-Reply-To: Your message of "Thu, 01 May 2003 00:00:58 MST." <20030501.000058.39187964.davem@redhat.com>
In message <20030501.000058.39187964.davem@redhat.com> you write:
> From: kuznet@ms2.inr.ac.ru
> Date: Thu, 1 May 2003 05:10:33 +0400 (MSD)
>
> [ Rusty, just skip down to "Ok ok ok!", it's something we've
> discussed before. Some of these problems are becomming so
> widespread that we need to implement a fix, I'll probably be
> the one to end up doing it... ]
>
> > 1) dev_get() gets module reference and dev_put() puts is.
> > Ugly, as this means dev_get() can fail, but this does
> > cover all the possible cases.
>
> Seems, you eventually _really_ understood why I histerically moan
> about bogosity of modules and maybe ready to recongnize that it is
> not just histerical moaning in some part. :-)
>
> Yes, I know, and we can talk about this until the cows come
> home... :-)
I agree with Alexey. Modules are poor-man's microkernel: allowing
them to be unloaded has always been a horror. But I failed to
convince my collegues of this at the 2002 kernel summit, so I did the
best with what we had. If I had my way, we would *never* remove
modules (even on failed init: we might re-try init later, but never
free the memory).
But before we redesign module architecture from scratch, let's look at
a solution with what we do have (assuming Linus takes my damn
__module_get() patch some day, see below).
There are 70 calls to dev_hold() in the kernel. The vast majority of
them already have a reference, they just want another one: dev_hold()
can do __module_get().
There are a few *sources* of devices: dev_get, dev_get_by*. These
should check and fail, using "try_dev_hold()" or something.
Unfortunately auditing all the __dev_get_by* is quite a task, since
it's used very widely (and I think, sometime erroneously).
Completely untested patch below other patch.
I need more time to digest your proposal in detail, Dave. Expect
reply w/in 24 hours.
Thanks.
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
Name: __module_get
Author: Rusty Russell
Status: Tested on 2.5.68-bk10
D: Introduces __module_get for places where we know we already hold
D: a reference and ignoring the fact that the module is being "rmmod --wait"ed
D: is simpler.
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .5001-linux-2.5.67-bk5/fs/filesystems.c .5001-linux-2.5.67-bk5.updated/fs/filesystems.c
--- .5001-linux-2.5.67-bk5/fs/filesystems.c 2003-04-14 13:45:44.000000000 +1000
+++ .5001-linux-2.5.67-bk5.updated/fs/filesystems.c 2003-04-14 15:44:36.000000000 +1000
@@ -32,17 +32,7 @@ static rwlock_t file_systems_lock = RW_L
/* WARNING: This can be used only if we _already_ own a reference */
void get_filesystem(struct file_system_type *fs)
{
- if (!try_module_get(fs->owner)) {
-#ifdef CONFIG_MODULE_UNLOAD
- unsigned int cpu = get_cpu();
- local_inc(&fs->owner->ref[cpu].count);
- put_cpu();
-#else
- /* Getting filesystem while it's starting up? We're
- already supposed to have a reference. */
- BUG();
-#endif
- }
+ __module_get(fs->owner);
}
void put_filesystem(struct file_system_type *fs)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .5001-linux-2.5.67-bk5/include/linux/module.h .5001-linux-2.5.67-bk5.updated/include/linux/module.h
--- .5001-linux-2.5.67-bk5/include/linux/module.h 2003-04-08 11:15:01.000000000 +1000
+++ .5001-linux-2.5.67-bk5.updated/include/linux/module.h 2003-04-14 15:45:15.000000000 +1000
@@ -255,6 +255,7 @@ struct module *module_text_address(unsig
#ifdef CONFIG_MODULE_UNLOAD
+unsigned int module_refcount(struct module *mod);
void __symbol_put(const char *symbol);
#define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x)
void symbol_put_addr(void *addr);
@@ -265,6 +266,17 @@ void symbol_put_addr(void *addr);
#define local_dec(x) atomic_dec(x)
#endif
+/* Sometimes we know we already have a refcount, and it's easier not
+ to handle the error case (which only happens with rmmod --wait). */
+static inline void __module_get(struct module *module)
+{
+ if (module) {
+ BUG_ON(module_refcount(module) == 0);
+ local_inc(&module->ref[get_cpu()].count);
+ put_cpu();
+ }
+}
+
static inline int try_module_get(struct module *module)
{
int ret = 1;
@@ -300,6 +317,9 @@ static inline int try_module_get(struct
static inline void module_put(struct module *module)
{
}
+static inline void __module_get(struct module *module)
+{
+}
#define symbol_put(x) do { } while(0)
#define symbol_put_addr(p) do { } while(0)
@@ -357,6 +377,10 @@ static inline struct module *module_text
#define symbol_put(x) do { } while(0)
#define symbol_put_addr(x) do { } while(0)
+static inline void __module_get(struct module *module)
+{
+}
+
static inline int try_module_get(struct module *module)
{
return 1;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .5001-linux-2.5.67-bk5/kernel/module.c .5001-linux-2.5.67-bk5.updated/kernel/module.c
--- .5001-linux-2.5.67-bk5/kernel/module.c 2003-04-14 13:45:46.000000000 +1000
+++ .5001-linux-2.5.67-bk5.updated/kernel/module.c 2003-04-14 15:44:36.000000000 +1000
@@ -431,7 +431,7 @@ static inline void restart_refcounts(voi
}
#endif
-static unsigned int module_refcount(struct module *mod)
+unsigned int module_refcount(struct module *mod)
{
unsigned int i, total = 0;
@@ -439,6 +439,7 @@ static unsigned int module_refcount(stru
total += atomic_read(&mod->ref[i].count);
return total;
}
+EXPORT_SYMBOL(module_refcount);
/* This exists whether we can unload or not */
static void free_module(struct module *mod);
================
Name: try_dev_hold
Author: Rusty Russell
Status: Experimental
Depends: Module/module_dup.patch.gz
D: Make dev_hold() actually duplicate the module reference count, and
D: introduce try_dev_hold() for where refcount may be zero. Some
D: places seemed to use dev_hold() to initialize the device reference
D: count to 1.
D:
D: Lots of fixmes caused by quick audit of __dev_get_by* and
D: dev_getbyhwaddr.
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/drivers/net/shaper.c working-2.5.68-bk10-netdevice/drivers/net/shaper.c
--- linux-2.5.68-bk10/drivers/net/shaper.c 2003-04-08 11:14:26.000000000 +1000
+++ working-2.5.68-bk10-netdevice/drivers/net/shaper.c 2003-05-01 21:21:46.000000000 +1000
@@ -526,6 +526,7 @@ static int shaper_neigh_setup_dev(struct
static int shaper_attach(struct net_device *shdev, struct shaper *sh, struct net_device *dev)
{
+ /* FIXME: No reference to dev --RR */
sh->dev = dev;
sh->hard_start_xmit=dev->hard_start_xmit;
sh->get_stats=dev->get_stats;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/drivers/net/wan/dlci.c working-2.5.68-bk10-netdevice/drivers/net/wan/dlci.c
--- linux-2.5.68-bk10/drivers/net/wan/dlci.c 2003-03-18 05:01:46.000000000 +1100
+++ working-2.5.68-bk10-netdevice/drivers/net/wan/dlci.c 2003-05-01 21:20:31.000000000 +1000
@@ -457,6 +457,7 @@ int dlci_add(struct dlci_add *dlci)
*(short *)(master->dev_addr) = dlci->dlci;
dlp = (struct dlci_local *) master->priv;
+ /* FIXME: We have no reference to slave here. --RR */
dlp->slave = slave;
flp = slave->priv;
@@ -484,6 +485,7 @@ int dlci_del(struct dlci_add *dlci)
/* validate slave device */
master = __dev_get_by_name(dlci->devname);
+ /* FIXME: No lock, no reference held to master. --RR */
if (!master)
return(-ENODEV);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/include/linux/netdevice.h working-2.5.68-bk10-netdevice/include/linux/netdevice.h
--- linux-2.5.68-bk10/include/linux/netdevice.h 2003-04-08 11:15:01.000000000 +1000
+++ working-2.5.68-bk10-netdevice/include/linux/netdevice.h 2003-05-01 20:03:27.000000000 +1000
@@ -29,6 +29,7 @@
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/kobject.h>
+#include <linux/module.h>
#include <asm/atomic.h>
#include <asm/cache.h>
@@ -634,7 +635,25 @@ static inline void dev_put(struct net_de
}
#define __dev_put(dev) atomic_dec(&(dev)->refcnt)
-#define dev_hold(dev) atomic_inc(&(dev)->refcnt)
+
+/* If you already have a reference, and are duplicating it. */
+#define dev_hold(dev) \
+do { \
+ atomic_inc(&(dev)->refcnt); \
+ __module_get((dev)->owner); \
+} while(0)
+
+/* If you need a new reference, or will be holding it for a long time.
+ If this returns 0, pretend dev doesn't exist (it's being removed now). */
+#define try_dev_hold(dev) \
+({ \
+ int __ret = 1; \
+ if (try_module_get((dev)->owner)) \
+ atomic_inc(&(dev)->refcnt); \
+ else \
+ __ret = 0; \
+ __ret; \
+})
/* Carrier loss detection, dial on demand. The functions netif_carrier_on
* and _off may be called from IRQ context, but it is caller
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/802/tr.c working-2.5.68-bk10-netdevice/net/802/tr.c
--- linux-2.5.68-bk10/net/802/tr.c 2003-02-07 19:21:54.000000000 +1100
+++ working-2.5.68-bk10-netdevice/net/802/tr.c 2003-05-01 21:24:46.000000000 +1000
@@ -479,6 +479,7 @@ static int rif_get_info(char *buffer,cha
for(i=0;i < RIF_TABLE_SIZE;i++)
{
for(entry=rif_table[i];entry;entry=entry->next) {
+ /* FIXME: No lock, and no reference to dev. --RR */
struct net_device *dev = __dev_get_by_index(entry->iface);
size=sprintf(buffer+len,"%s %02X:%02X:%02X:%02X:%02X:%02X %7li ",
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/appletalk/ddp.c working-2.5.68-bk10-netdevice/net/appletalk/ddp.c
--- linux-2.5.68-bk10/net/appletalk/ddp.c 2003-05-01 09:29:34.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/appletalk/ddp.c 2003-05-01 21:28:03.000000000 +1000
@@ -920,6 +920,7 @@ static int atrtr_ioctl(unsigned int cmd,
* space, isn't it?
*/
if (rt.rt_dev) {
+ /* FIXME: No lock, and no reference to dev --RR */
dev = __dev_get_by_name(rt.rt_dev);
if (!dev)
return -ENODEV;
@@ -1217,6 +1218,7 @@ static __inline__ int is_ip_over_ddp(str
static int handle_ip_over_ddp(struct sk_buff *skb)
{
+ /* FIXME: No lock, and no reference held to dev. --RR */
struct net_device *dev = __dev_get_by_name("ipddp0");
struct net_device_stats *stats;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/core/dev.c working-2.5.68-bk10-netdevice/net/core/dev.c
--- linux-2.5.68-bk10/net/core/dev.c 2003-05-01 09:29:35.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/core/dev.c 2003-05-01 20:19:24.000000000 +1000
@@ -440,8 +440,8 @@ struct net_device *dev_get_by_name(const
read_lock(&dev_base_lock);
dev = __dev_get_by_name(name);
- if (dev)
- dev_hold(dev);
+ if (dev && !try_dev_hold(dev))
+ dev = NULL;
read_unlock(&dev_base_lock);
return dev;
}
@@ -513,8 +513,8 @@ struct net_device *dev_get_by_index(int
read_lock(&dev_base_lock);
dev = __dev_get_by_index(ifindex);
- if (dev)
- dev_hold(dev);
+ if (dev && !try_dev_hold(dev))
+ dev = NULL;
read_unlock(&dev_base_lock);
return dev;
}
@@ -563,8 +563,8 @@ struct net_device * dev_get_by_flags(uns
read_lock(&dev_base_lock);
dev = __dev_get_by_flags(if_flags, mask);
- if (dev)
- dev_hold(dev);
+ if (dev && !try_dev_hold(dev))
+ dev = NULL;
read_unlock(&dev_base_lock);
return dev;
}
@@ -2611,7 +2611,7 @@ int register_netdevice(struct net_device
dev_init_scheduler(dev);
write_lock_bh(&dev_base_lock);
*dp = dev;
- dev_hold(dev);
+ atomic_set(&dev->refcnt, 1);
dev->deadbeaf = 0;
write_unlock_bh(&dev_base_lock);
@@ -2899,7 +2899,7 @@ static int __init net_dev_init(void)
#endif
dev->xmit_lock_owner = -1;
dev->iflink = -1;
- dev_hold(dev);
+ atomic_set(&dev->refcnt, 1);
/*
* Allocate name. If the init() fails
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/core/pktgen.c working-2.5.68-bk10-netdevice/net/core/pktgen.c
--- linux-2.5.68-bk10/net/core/pktgen.c 2003-05-01 09:29:35.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/core/pktgen.c 2003-05-01 21:31:45.000000000 +1000
@@ -226,21 +226,20 @@ static struct net_device *setup_inject(s
{
struct net_device *odev;
- rtnl_lock();
- odev = __dev_get_by_name(info->outdev);
+ odev = dev_get(info->outdev);
if (!odev) {
sprintf(info->result, "No such netdevice: \"%s\"", info->outdev);
- goto out_unlock;
+ return NULL;
}
if (odev->type != ARPHRD_ETHER) {
sprintf(info->result, "Not ethernet device: \"%s\"", info->outdev);
- goto out_unlock;
+ goto out_put;
}
if (!netif_running(odev)) {
sprintf(info->result, "Device is down: \"%s\"", info->outdev);
- goto out_unlock;
+ goto out_put;
}
/* Default to the interface's mac if not explicitly set. */
@@ -281,14 +280,11 @@ static struct net_device *setup_inject(s
info->cur_daddr = info->daddr_min;
info->cur_udp_dst = info->udp_dst_min;
info->cur_udp_src = info->udp_src_min;
-
- atomic_inc(&odev->refcnt);
- rtnl_unlock();
return odev;
-out_unlock:
- rtnl_unlock();
+out_put:
+ dev_put(odev);
return NULL;
}
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/decnet/dn_dev.c working-2.5.68-bk10-netdevice/net/decnet/dn_dev.c
--- linux-2.5.68-bk10/net/decnet/dn_dev.c 2003-04-20 18:05:16.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/decnet/dn_dev.c 2003-05-01 21:35:29.000000000 +1000
@@ -312,9 +312,7 @@ struct net_device *dn_dev_get_default(vo
read_lock(&dndev_lock);
dev = decnet_default_device;
if (dev) {
- if (dev->dn_ptr)
- dev_hold(dev);
- else
+ if (!dev->dn_ptr || !try_dev_hold(dev))
dev = NULL;
}
read_unlock(&dndev_lock);
@@ -584,6 +582,8 @@ int dn_dev_ioctl(unsigned int cmd, void
goto done;
}
+ /* FIXME: if cmd == SIOCGIFADDR, don't hold lock, and don't
+ have reference to dev. --RR */
if ((dn_db = dev->dn_ptr) != NULL) {
for (ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next)
if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0)
@@ -677,6 +677,7 @@ static int dn_dev_rtm_newaddr(struct sk_
if (rta[IFA_LOCAL-1] == NULL)
return -EINVAL;
+ /* FIXME: Don't have lock, and don't hold reference to dev. --RR */
if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
return -ENODEV;
@@ -1189,9 +1190,10 @@ void dn_dev_up(struct net_device *dev)
* configured ethernet card in the system.
*/
if (maybe_default) {
- dev_hold(dev);
- if (dn_dev_set_default(dev, 0))
- dev_put(dev);
+ if (try_dev_hold(dev)) {
+ if (dn_dev_set_default(dev, 0))
+ dev_put(dev);
+ }
}
}
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/decnet/dn_fib.c working-2.5.68-bk10-netdevice/net/decnet/dn_fib.c
--- linux-2.5.68-bk10/net/decnet/dn_fib.c 2003-04-20 18:05:16.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/decnet/dn_fib.c 2003-05-01 21:43:34.000000000 +1000
@@ -218,7 +218,9 @@ static int dn_fib_check_nh(const struct
if (!(dev->flags&IFF_UP))
return -ENETDOWN;
nh->nh_dev = dev;
- atomic_inc(&dev->refcnt);
+ /* FIXME: Must hold lock, or use dev_get_by_index.
+ --RR */
+ dev_hold(dev);
nh->nh_scope = RT_SCOPE_LINK;
return 0;
}
@@ -262,7 +264,7 @@ out:
if (!(dev->flags&IFF_UP))
return -ENETDOWN;
nh->nh_dev = dev;
- atomic_inc(&nh->nh_dev->refcnt);
+ dev_hold(&nh->nh_dev);
nh->nh_scope = RT_SCOPE_HOST;
}
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/decnet/dn_route.c working-2.5.68-bk10-netdevice/net/decnet/dn_route.c
--- linux-2.5.68-bk10/net/decnet/dn_route.c 2003-05-01 09:29:35.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/decnet/dn_route.c 2003-05-01 20:58:08.000000000 +1000
@@ -891,7 +891,9 @@ static int dn_route_output_slow(struct d
read_unlock(&dev_base_lock);
if (dev_out == NULL)
goto out;
- dev_hold(dev_out);
+ /* FIXME: Shouldn't this be inside the lock? --RR */
+ if (!try_dev_hold(dev_out))
+ goto out;
source_ok:
;
}
@@ -960,8 +962,10 @@ source_ok:
} else {
dev_out = neigh->dev;
}
- dev_hold(dev_out);
- goto select_source;
+ if (try_dev_hold(dev_out))
+ goto select_source;
+ else
+ dev_out = NULL;
}
}
}
@@ -1035,7 +1039,10 @@ select_source:
if (dev_out)
dev_put(dev_out);
dev_out = DN_FIB_RES_DEV(res);
- dev_hold(dev_out);
+ if (!try_dev_hold(dev_out)) {
+ dev_out = NULL;
+ goto e_addr;
+ }
fl.oif = dev_out->ifindex;
gateway = DN_FIB_RES_GW(res);
@@ -1231,7 +1238,8 @@ static int dn_route_input_slow(struct sk
"No output device\n");
goto e_inval;
}
- dev_hold(out_dev);
+ if (!try_dev_hold(out_dev))
+ goto e_inval;
if (res.r)
src_map = dn_fib_rules_policy(fl.fld_src, &res, &flags);
@@ -1349,8 +1357,12 @@ make_route:
rt->u.dst.input = dn_blackhole;
}
rt->rt_flags = flags;
- if (rt->u.dst.dev)
- dev_hold(rt->u.dst.dev);
+ if (rt->u.dst.dev) {
+ if (!try_dev_hold(rt->u.dst.dev)) {
+ dst_free(&rt->u.dst);
+ goto e_inval;
+ }
+ }
if (dn_rt_set_next_hop(rt, &res))
goto e_neighbour;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/decnet/dn_rules.c working-2.5.68-bk10-netdevice/net/decnet/dn_rules.c
--- linux-2.5.68-bk10/net/decnet/dn_rules.c 2003-04-20 18:05:16.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/decnet/dn_rules.c 2003-05-01 21:37:58.000000000 +1000
@@ -173,6 +173,7 @@ int dn_fib_rtm_newrule(struct sk_buff *s
memcpy(new_r->r_ifname, RTA_DATA(rta[RTA_IIF-1]), IFNAMSIZ);
new_r->r_ifname[IFNAMSIZ-1] = 0;
new_r->r_ifindex = -1;
+ /* FIXME: Don't hold lock, and don't get reference. --RR */
dev = __dev_get_by_name(new_r->r_ifname);
if (dev)
new_r->r_ifindex = dev->ifindex;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/ipv4/fib_frontend.c working-2.5.68-bk10-netdevice/net/ipv4/fib_frontend.c
--- linux-2.5.68-bk10/net/ipv4/fib_frontend.c 2003-05-01 20:36:37.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/ipv4/fib_frontend.c 2003-01-02 12:30:47.000000000 +1100
@@ -115,8 +115,8 @@ struct net_device * ip_dev_find(u32 addr
if (res.type != RTN_LOCAL)
goto out;
dev = FIB_RES_DEV(res);
- if (dev && !try_dev_get(dev))
- dev = NULL;
+ if (dev)
+ atomic_inc(&dev->refcnt);
out:
fib_res_put(&res);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/ipv4/fib_semantics.c working-2.5.68-bk10-netdevice/net/ipv4/fib_semantics.c
--- linux-2.5.68-bk10/net/ipv4/fib_semantics.c 2003-05-01 09:29:35.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/ipv4/fib_semantics.c 2003-05-01 21:39:20.000000000 +1000
@@ -405,6 +405,8 @@ static int fib_check_nh(const struct rtm
return -ENODEV;
if (!(dev->flags&IFF_UP))
return -ENETDOWN;
+ /* FIXME: Must hold lock, or use dev_get_by_index.
+ --RR */
nh->nh_dev = dev;
atomic_inc(&dev->refcnt);
nh->nh_scope = RT_SCOPE_LINK;
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/ipv4/ip_gre.c working-2.5.68-bk10-netdevice/net/ipv4/ip_gre.c
--- linux-2.5.68-bk10/net/ipv4/ip_gre.c 2003-05-01 09:29:35.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/ipv4/ip_gre.c 2003-05-01 21:50:07.000000000 +1000
@@ -289,7 +289,7 @@ static struct ip_tunnel * ipgre_tunnel_l
if (register_netdevice(dev) < 0)
goto failed;
- dev_hold(dev);
+ atomic_set(&dev->refcnt, 1);
ipgre_tunnel_link(nt);
/* Do not decrement MOD_USE_COUNT here. */
return nt;
@@ -1205,6 +1205,7 @@ static int ipgre_tunnel_init(struct net_
}
if (!tdev && tunnel->parms.link)
+ /* FIXME: Don't hold lock, don't grab reference. --RR */
tdev = __dev_get_by_index(tunnel->parms.link);
if (tdev) {
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/ipv4/ipip.c working-2.5.68-bk10-netdevice/net/ipv4/ipip.c
--- linux-2.5.68-bk10/net/ipv4/ipip.c 2003-04-20 18:05:16.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/ipv4/ipip.c 2003-05-01 21:51:47.000000000 +1000
@@ -259,7 +259,7 @@ static struct ip_tunnel * ipip_tunnel_lo
if (register_netdevice(dev) < 0)
goto failed;
- dev_hold(dev);
+ atomic_set(&dev->refcnt, 1);
ipip_tunnel_link(nt);
/* Do not decrement MOD_USE_COUNT here. */
return nt;
@@ -841,6 +841,7 @@ static int ipip_tunnel_init(struct net_d
}
if (!tdev && tunnel->parms.link)
+ /* FIXME: Don't hold lock, don't grab reference. --RR */
tdev = __dev_get_by_index(tunnel->parms.link);
if (tdev) {
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/ipv4/ipmr.c working-2.5.68-bk10-netdevice/net/ipv4/ipmr.c
--- linux-2.5.68-bk10/net/ipv4/ipmr.c 2003-03-25 12:17:32.000000000 +1100
+++ working-2.5.68-bk10-netdevice/net/ipv4/ipmr.c 2003-05-01 20:39:29.000000000 +1000
@@ -443,7 +443,6 @@ static int vif_add(struct vifctl *vifc,
/* And finish update writing critical data */
write_lock_bh(&mrt_lock);
- dev_hold(dev);
v->dev=dev;
#ifdef CONFIG_IP_PIMSM
if (v->flags&VIFF_REGISTER)
@@ -1441,8 +1440,8 @@ int pim_rcv_v1(struct sk_buff * skb)
read_lock(&mrt_lock);
if (reg_vif_num >= 0)
reg_dev = vif_table[reg_vif_num].dev;
- if (reg_dev)
- dev_hold(reg_dev);
+ if (reg_dev && !try_dev_hold(reg_dev))
+ reg_dev = NULL;
read_unlock(&mrt_lock);
if (reg_dev == NULL) {
@@ -1508,8 +1507,8 @@ int pim_rcv(struct sk_buff * skb)
read_lock(&mrt_lock);
if (reg_vif_num >= 0)
reg_dev = vif_table[reg_vif_num].dev;
- if (reg_dev)
- dev_hold(reg_dev);
+ if (reg_dev && !try_dev_hold(reg_dev))
+ reg_dev = NULL;
read_unlock(&mrt_lock);
if (reg_dev == NULL) {
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/ipv4/route.c working-2.5.68-bk10-netdevice/net/ipv4/route.c
--- linux-2.5.68-bk10/net/ipv4/route.c 2003-05-01 09:29:35.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/ipv4/route.c 2003-05-01 20:41:28.000000000 +1000
@@ -1992,7 +1992,8 @@ int ip_route_output_slow(struct rtable *
if (dev_out)
dev_put(dev_out);
dev_out = FIB_RES_DEV(res);
- dev_hold(dev_out);
+ if (!try_dev_hold(dev_out))
+ goto e_inval;
fl.oif = dev_out->ifindex;
make_route:
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/ipv6/sit.c working-2.5.68-bk10-netdevice/net/ipv6/sit.c
--- linux-2.5.68-bk10/net/ipv6/sit.c 2003-04-20 18:05:17.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/ipv6/sit.c 2003-05-01 21:55:21.000000000 +1000
@@ -197,7 +197,7 @@ static struct ip_tunnel * ipip6_tunnel_l
if (register_netdevice(dev) < 0)
goto failed;
- dev_hold(dev);
+ atomic_set(&dev->refcount, 1);
ipip6_tunnel_link(nt);
/* Do not decrement MOD_USE_COUNT here. */
return nt;
@@ -778,6 +778,7 @@ static int ipip6_tunnel_init(struct net_
}
if (!tdev && tunnel->parms.link)
+ /* FIXME: Don't hold lock, don't grab reference. --RR */
tdev = __dev_get_by_index(tunnel->parms.link);
if (tdev) {
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/llc/af_llc.c working-2.5.68-bk10-netdevice/net/llc/af_llc.c
--- linux-2.5.68-bk10/net/llc/af_llc.c 2003-05-01 09:29:36.000000000 +1000
+++ working-2.5.68-bk10-netdevice/net/llc/af_llc.c 2003-05-01 21:13:49.000000000 +1000
@@ -256,6 +256,7 @@ static int llc_ui_autobind(struct socket
rc = -ENETUNREACH;
if (!dev)
goto out;
+ /* FIXME: We don't hold a reference to dev --RR */
llc->dev = dev;
}
/* bind to a specific sap, optional. */
@@ -419,6 +420,7 @@ static int llc_ui_connect(struct socket
rtnl_unlock();
if (!dev)
goto out;
+ /* FIXME: We don't hold a reference to dev --RR */
llc->dev = dev;
} else
dev = llc->dev;
@@ -764,6 +766,7 @@ static int llc_ui_sendmsg(struct kiocb *
dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac);
rtnl_unlock();
rc = -ENETUNREACH;
+ /* FIXME: We don't hold a reference to dev --RR */
if (!dev)
goto release;
} else
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/netrom/nr_route.c working-2.5.68-bk10-netdevice/net/netrom/nr_route.c
--- linux-2.5.68-bk10/net/netrom/nr_route.c 2003-01-02 12:27:51.000000000 +1100
+++ working-2.5.68-bk10-netdevice/net/netrom/nr_route.c 2003-05-01 20:51:51.000000000 +1000
@@ -567,8 +567,8 @@ struct net_device *nr_dev_get(ax25_addre
read_lock(&dev_base_lock);
for (dev = dev_base; dev != NULL; dev = dev->next) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
- dev_hold(dev);
- goto out;
+ if (try_dev_hold(dev))
+ goto out;
}
}
out:
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.68-bk10/net/rose/rose_route.c working-2.5.68-bk10-netdevice/net/rose/rose_route.c
--- linux-2.5.68-bk10/net/rose/rose_route.c 2003-03-18 12:21:41.000000000 +1100
+++ working-2.5.68-bk10-netdevice/net/rose/rose_route.c 2003-05-01 20:51:59.000000000 +1000
@@ -629,8 +629,8 @@ struct net_device *rose_dev_get(rose_add
read_lock(&dev_base_lock);
for (dev = dev_base; dev != NULL; dev = dev->next) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
- dev_hold(dev);
- goto out;
+ if (try_dev_hold(dev))
+ goto out;
}
}
out:
next prev parent reply other threads:[~2003-05-01 12:01 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-04-30 6:26 dev->destructor David S. Miller
2003-04-30 16:33 ` dev->destructor Stephen Hemminger
2003-05-01 1:10 ` dev->destructor kuznet
2003-05-01 7:00 ` dev->destructor David S. Miller
2003-05-01 12:01 ` Rusty Russell [this message]
2003-05-01 11:09 ` dev->destructor David S. Miller
2003-05-01 17:51 ` dev->destructor Arnaldo Carvalho de Melo
2003-05-01 16:55 ` dev->destructor David S. Miller
2003-05-01 17:28 ` dev->destructor Arnaldo Carvalho de Melo
2003-05-02 4:06 ` dev->destructor kuznet
2003-05-02 5:25 ` dev->destructor Rusty Russell
2003-05-02 20:48 ` dev->destructor David S. Miller
2003-05-03 4:07 ` dev->destructor Rusty Russell
2003-05-03 3:46 ` dev->destructor David S. Miller
2003-05-05 5:18 ` dev->destructor Rusty Russell
2003-05-03 4:00 ` dev->destructor David S. Miller
2003-05-05 16:08 ` dev->destructor Stephen Hemminger
2003-05-06 14:25 ` dev->destructor David S. Miller
2003-05-07 2:54 ` dev->destructor Rusty Russell
2003-05-05 20:00 ` dev->destructor Stephen Hemminger
2003-05-06 4:18 ` dev->destructor Rusty Russell
2003-05-06 14:23 ` dev->destructor David S. Miller
2003-05-06 22:32 ` [PATCH 2.5.69] IPV4 should use dev_hold Stephen Hemminger
2003-05-07 7:32 ` David S. Miller
2003-05-07 2:50 ` dev->destructor Rusty Russell
2003-05-07 3:58 ` dev->destructor David S. Miller
2003-05-06 22:35 ` dev->destructor Stephen Hemminger
2003-05-06 23:51 ` [RFC] Experiment with dev and module ref counts Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20030501120815.25BE22C155@lists.samba.org \
--to=rusty@rustcorp.com.au \
--cc=davem@redhat.com \
--cc=kuznet@ms2.inr.ac.ru \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).