From b4d745db12bd2d45a456565ed63325bbfc689e68 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 4 Nov 2009 10:59:38 -0800 Subject: decnet: avoid touching device refcount in dn_dev_by_index() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/decnet/dn_dev.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'net/decnet/dn_dev.c') diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 6e1f085db06..d82694d930b 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -600,15 +600,17 @@ static void dn_dev_check_default(struct net_device *dev) dev_put(dev); } +/* + * Called with RTNL + */ static struct dn_dev *dn_dev_by_index(int ifindex) { struct net_device *dev; struct dn_dev *dn_dev = NULL; - dev = dev_get_by_index(&init_net, ifindex); - if (dev) { + + dev = __dev_get_by_index(&init_net, ifindex); + if (dev) dn_dev = dev->dn_ptr; - dev_put(dev); - } return dn_dev; } -- cgit v1.2.3-18-g5258 From fa918602b61a71b4a9f47861b7e65c70258516c1 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 10 Nov 2009 07:54:53 +0000 Subject: decnet: use RCU to find network devices When showing device statistics use RCU rather than read_lock(&dev_base_lock) Compile tested only. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/decnet/dn_dev.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'net/decnet/dn_dev.c') diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index d82694d930b..b5ef237c8a7 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -856,9 +856,7 @@ int dn_dev_bind_default(__le16 *addr) dev = dn_dev_get_default(); last_chance: if (dev) { - read_lock(&dev_base_lock); rv = dn_dev_get_first(dev, addr); - read_unlock(&dev_base_lock); dev_put(dev); if (rv == 0 || dev == init_net.loopback_dev) return rv; @@ -1323,18 +1321,18 @@ static inline int is_dn_dev(struct net_device *dev) } static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(&dev_base_lock) + __acquires(rcu) { int i; struct net_device *dev; - read_lock(&dev_base_lock); + rcu_read_lock(); if (*pos == 0) return SEQ_START_TOKEN; i = 1; - for_each_netdev(&init_net, dev) { + for_each_netdev_rcu(&init_net, dev) { if (!is_dn_dev(dev)) continue; @@ -1355,7 +1353,7 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) if (v == SEQ_START_TOKEN) dev = net_device_entry(&init_net.dev_base_head); - for_each_netdev_continue(&init_net, dev) { + for_each_netdev_continue_rcu(&init_net, dev) { if (!is_dn_dev(dev)) continue; @@ -1366,9 +1364,9 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void dn_dev_seq_stop(struct seq_file *seq, void *v) - __releases(&dev_base_lock) + __releases(rcu) { - read_unlock(&dev_base_lock); + rcu_read_unlock(); } static char *dn_type2asc(char type) -- cgit v1.2.3-18-g5258 From 41bdecf17e6dba92256c65972ec79a482d978be5 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 11 Nov 2009 07:39:27 +0000 Subject: decnet: add RTNL lock when reading address list Add missing locking in the case of auto binding to the default device. The address list might change while this code is looking at the list. Compile tested only, I am not a decnet user. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/decnet/dn_dev.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net/decnet/dn_dev.c') diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index b5ef237c8a7..5790d660bc7 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -828,13 +828,17 @@ static int dn_dev_get_first(struct net_device *dev, __le16 *addr) struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; struct dn_ifaddr *ifa; int rv = -ENODEV; + if (dn_db == NULL) goto out; + + rtnl_lock(); ifa = dn_db->ifa_list; if (ifa != NULL) { *addr = ifa->ifa_local; rv = 0; } + rtnl_unlock(); out: return rv; } -- cgit v1.2.3-18-g5258 From e5c140a340c4796054b0f6e9035e1faa7edfa6d6 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 11 Nov 2009 07:40:36 +0000 Subject: decnet: convert dndev_lock to spinlock There is no reason for this lock to be reader/writer since the reader only has lock held for a very brief period. The overhead of read_lock is more expensive than spinlock. Compile tested only, I am not a decnet user. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/decnet/dn_dev.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'net/decnet/dn_dev.c') diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 5790d660bc7..6c916e2b8a8 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -68,7 +68,7 @@ extern struct neigh_table dn_neigh_table; */ __le16 decnet_address = 0; -static DEFINE_RWLOCK(dndev_lock); +static DEFINE_SPINLOCK(dndev_lock); static struct net_device *decnet_default_device; static BLOCKING_NOTIFIER_HEAD(dnaddr_chain); @@ -557,7 +557,8 @@ rarok: struct net_device *dn_dev_get_default(void) { struct net_device *dev; - read_lock(&dndev_lock); + + spin_lock(&dndev_lock); dev = decnet_default_device; if (dev) { if (dev->dn_ptr) @@ -565,7 +566,8 @@ struct net_device *dn_dev_get_default(void) else dev = NULL; } - read_unlock(&dndev_lock); + spin_unlock(&dndev_lock); + return dev; } @@ -575,13 +577,15 @@ int dn_dev_set_default(struct net_device *dev, int force) int rv = -EBUSY; if (!dev->dn_ptr) return -ENODEV; - write_lock(&dndev_lock); + + spin_lock(&dndev_lock); if (force || decnet_default_device == NULL) { old = decnet_default_device; decnet_default_device = dev; rv = 0; } - write_unlock(&dndev_lock); + spin_unlock(&dndev_lock); + if (old) dev_put(old); return rv; @@ -589,13 +593,14 @@ int dn_dev_set_default(struct net_device *dev, int force) static void dn_dev_check_default(struct net_device *dev) { - write_lock(&dndev_lock); + spin_lock(&dndev_lock); if (dev == decnet_default_device) { decnet_default_device = NULL; } else { dev = NULL; } - write_unlock(&dndev_lock); + spin_unlock(&dndev_lock); + if (dev) dev_put(dev); } -- cgit v1.2.3-18-g5258 From 09ad9bc752519cc167d0a573e1acf69b5c707c67 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Wed, 25 Nov 2009 15:14:13 -0800 Subject: net: use net_eq to compare nets Generated with the following semantic patch @@ struct net *n1; struct net *n2; @@ - n1 == n2 + net_eq(n1, n2) @@ struct net *n1; struct net *n2; @@ - n1 != n2 + !net_eq(n1, n2) applied over {include,net,drivers/net}. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller --- net/decnet/dn_dev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/decnet/dn_dev.c') diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 6c916e2b8a8..f20dec9cfa0 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -636,7 +636,7 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) struct dn_ifaddr *ifa, **ifap; int err = -EINVAL; - if (net != &init_net) + if (!net_eq(net, &init_net)) goto errout; err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy); @@ -675,7 +675,7 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) struct dn_ifaddr *ifa; int err; - if (net != &init_net) + if (!net_eq(net, &init_net)) return -EINVAL; err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy); @@ -789,7 +789,7 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) struct dn_dev *dn_db; struct dn_ifaddr *ifa; - if (net != &init_net) + if (!net_eq(net, &init_net)) return 0; skip_ndevs = cb->args[0]; -- cgit v1.2.3-18-g5258