Netdev List
 help / color / mirror / Atom feed
* Re: [patch 7/11] net: Use bigrefs for net_device.refcount
From: Ben Greear @ 2005-09-13 16:35 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Ravikiran G Thirumalai, Andrew Morton, linux-kernel, dipankar,
	bharata, shai, Rusty Russell, netdev, davem
In-Reply-To: <20050913092659.791bddec@localhost.localdomain>

Stephen Hemminger wrote:
> On Tue, 13 Sep 2005 09:10:12 -0700
> Ravikiran G Thirumalai <kiran@scalex86.org> wrote:
> 
> 
>>The net_device has a refcnt used to keep track of it's uses.
>>This is used at the time of unregistering the network device
>>(module unloading ..) (see netdev_wait_allrefs) .
>>For loopback_dev , this refcnt increment/decrement  is causing
>>unnecessary traffic on the interlink for NUMA system
>>affecting it's performance.  This patch improves tbench numbers by 6% on a
>>8way x86 Xeon (x445).
>>
> 
> 
> Since when is bringing a network device up/down performance critical?

We grab and drop a reference for each poll of a device, roughly.

See dev_hold in _netif_rx_schedule(struct net_device *dev)
in include/netdevice.h, for instance.

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com

^ permalink raw reply

* Re: [patch 7/11] net: Use bigrefs for net_device.refcount
From: Stephen Hemminger @ 2005-09-13 16:26 UTC (permalink / raw)
  To: Ravikiran G Thirumalai
  Cc: Andrew Morton, linux-kernel, dipankar, bharata, shai,
	Rusty Russell, netdev, davem
In-Reply-To: <20050913161012.GI3570@localhost.localdomain>

On Tue, 13 Sep 2005 09:10:12 -0700
Ravikiran G Thirumalai <kiran@scalex86.org> wrote:

> The net_device has a refcnt used to keep track of it's uses.
> This is used at the time of unregistering the network device
> (module unloading ..) (see netdev_wait_allrefs) .
> For loopback_dev , this refcnt increment/decrement  is causing
> unnecessary traffic on the interlink for NUMA system
> affecting it's performance.  This patch improves tbench numbers by 6% on a
> 8way x86 Xeon (x445).
> 

Since when is bringing a network device up/down performance critical?

^ permalink raw reply

* [patch 9/11] net: dst_entry.refcount, use, lastuse to use alloc_percpu
From: Ravikiran G Thirumalai @ 2005-09-13 16:17 UTC (permalink / raw)
  To: Andrew Morton
  Cc: linux-kernel, dipankar, bharata, shai, Rusty Russell, netdev,
	davem
In-Reply-To: <20050913155112.GB3570@localhost.localdomain>

Patch to use alloc_percpu for dst_entry.refcount.  This patch reduces the
cacheline bouncing of the atomic_t dst_entry.__refcount.  This Patch gets us
55% better tbench throughput, on a 8way x445 box.

Signed-off by: Pravin B. Shelar <pravins@calsoftinc.com>
Signed-off by: Shobhit Dayal <shobhit@calsoftinc.com>
Signed-off by: Christoph Lameter <christoph@lameter.com>
Signed-off by: Ravikiran Thirumalai <kirant@scalex86.org>

Index: alloc_percpu-2.6.13/include/net/dst.h
===================================================================
--- alloc_percpu-2.6.13.orig/include/net/dst.h	2005-09-12 12:23:37.000000000 -0700
+++ alloc_percpu-2.6.13/include/net/dst.h	2005-09-12 16:44:05.000000000 -0700
@@ -35,11 +35,33 @@
 
 struct sk_buff;
 
+#ifdef CONFIG_NUMA
+
+/*	A per cpu instance of this exist for every dst_entry.
+ *	These are the most written fields of dst_entry.
+ */
+struct per_cpu_cnt
+{
+	int 		refcnt;
+	int 		use;
+	unsigned long	lastuse;
+};
+
+#endif
+
 struct dst_entry
 {
 	struct dst_entry        *next;
+#ifdef CONFIG_NUMA
+	/* first cpu that should be checked for time-out */
+	int 			s_cpu;
+	/* per cpu client references   */
+	struct per_cpu_cnt	*pcc;
+#else
 	atomic_t		__refcnt;	/* client references	*/
 	int			__use;
+	unsigned long		lastuse;
+#endif
 	struct dst_entry	*child;
 	struct net_device       *dev;
 	short			error;
@@ -50,7 +72,6 @@
 #define DST_NOPOLICY		4
 #define DST_NOHASH		8
 #define DST_BALANCED            0x10
-	unsigned long		lastuse;
 	unsigned long		expires;
 
 	unsigned short		header_len;	/* more space at head required */
@@ -103,25 +124,94 @@
 
 #ifdef __KERNEL__
 
+#ifdef CONFIG_NUMA
+
+static inline int dst_use(struct dst_entry *dst)
+{
+	int total = 0, cpu;
+
+	for_each_online_cpu(cpu)
+		total += per_cpu_ptr(dst->pcc, cpu)->use;
+	return total;
+}
+
+#define dst_use_inc(__dst) do {					\
+		per_cpu_ptr((__dst)->pcc, get_cpu())->use++ ;	\
+		put_cpu();					\
+	} while(0);
+
+static inline unsigned long dst_lastuse(struct dst_entry *dst)
+{
+	unsigned long max = 0;
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		if (max < per_cpu_ptr(dst->pcc, cpu)->lastuse)
+			max = per_cpu_ptr(dst->pcc, cpu)->lastuse;
+	return max;
+}
+
+#define dst_lastuse_set(__dst)  do {					  \
+		per_cpu_ptr((__dst)->pcc, get_cpu())->lastuse = jiffies ; \
+		put_cpu();						  \
+	} while(0);
+
+static inline int dst_refcnt(struct dst_entry *dst)
+{
+	int cpu, sum = 0;
+
+	for_each_online_cpu(cpu)
+		sum += per_cpu_ptr(dst->pcc, cpu)->refcnt;
+
+	return sum;
+}
+
+#define dst_refcnt_one(__dst) do { 					  \
+			per_cpu_ptr((__dst)->pcc, get_cpu())->refcnt = 1; \
+			put_cpu();		  			  \
+		} while(0);
+
+#define dst_refcnt_dec(__dst) do { 					\
+			per_cpu_ptr((__dst)->pcc, get_cpu())->refcnt--;	\
+			put_cpu();					\
+		} while(0);
+#define dst_hold(__dst) do { 						 \
+			per_cpu_ptr((__dst)->pcc, get_cpu())->refcnt++ ; \
+			put_cpu();					 \
+		} while(0);
+
+#else
+
 #define dst_use(__dst) (__dst)->__use
 #define dst_use_inc(__dst) (__dst)->__use++
 
 #define dst_lastuse(__dst) (__dst)->lastuse
 #define dst_lastuse_set(__dst) (__dst)->lastuse = jiffies
 
-#define dst_update_tu(__dst) do { dst_lastuse_set(__dst);dst_use_inc(__dst); } while (0)
-#define dst_update_rtu(__dst) do { dst_lastuse_set(__dst);dst_hold(__dst);dst_use_inc(__dst); } while (0)
-
 #define dst_refcnt(__dst) atomic_read(&(__dst)->__refcnt)
 #define dst_refcnt_one(__dst) atomic_set(&(__dst)->__refcnt, 1)
 #define dst_refcnt_dec(__dst) atomic_dec(&(__dst)->__refcnt)
 #define dst_hold(__dst) atomic_inc(&(__dst)->__refcnt)
 
+#endif
+#define dst_update_tu(__dst) do { 		\
+		dst_lastuse_set(__dst);		\
+		dst_use_inc(__dst); 		\
+	} while (0);
+
+#define dst_update_rtu(__dst) do { 		\
+		dst_lastuse_set(__dst);		\
+		dst_hold(__dst);		\
+		dst_use_inc(__dst); 		\
+	} while (0)
+
 static inline
 void dst_release(struct dst_entry * dst)
 {
 	if (dst) {
+#if  (!defined (CONFIG_NUMA) || (RT_CACHE_DEBUG >= 2 ))
 		WARN_ON(dst_refcnt(dst) < 1);
+#endif
 		smp_mb__before_atomic_dec();
 		dst_refcnt_dec(dst);
 	}
@@ -271,6 +361,48 @@
 
 extern void		dst_init(void);
 
+/*	This function allocates and initializes rtu array of given dst-entry.
+ */
+static inline int dst_init_rtu_array(struct dst_entry *dst)
+{
+#ifdef CONFIG_NUMA
+	int cpu;
+	dst->pcc = alloc_percpu(struct per_cpu_cnt, GFP_ATOMIC);
+	if(!dst->pcc)
+		return -ENOMEM;
+
+	for_each_cpu(cpu) {
+		per_cpu_ptr(dst->pcc, cpu)->use = 0;
+		per_cpu_ptr(dst->pcc, cpu)->refcnt = 0;
+		per_cpu_ptr(dst->pcc, cpu)->lastuse = jiffies;
+	}
+	dst->s_cpu = smp_processor_id();
+#else
+	atomic_set(&dst->__refcnt, 0);
+	dst->lastuse = jiffies;
+#endif
+	return 0;
+}
+
+static inline void dst_free_rtu_array(struct dst_entry *dst)
+{
+#ifdef CONFIG_NUMA
+	free_percpu(dst->pcc);
+#endif
+}
+
+#if	defined (CONFIG_HOTPLUG_CPU) && defined (CONFIG_NUMA)
+inline static void dst_ref_xfr_cpu_down(struct dst_entry *__dst, int cpu)
+{
+	int refcnt = per_cpu_ptr((__dst)->pcc, cpu)->refcnt;
+	if (refcnt) {
+		per_cpu_ptr((__dst)->pcc, get_cpu())->refcnt += refcnt;
+		put_cpu();
+		per_cpu_ptr((__dst)->pcc, cpu)->refcnt = 0;
+	}
+}
+#endif
+
 struct flowi;
 #ifndef CONFIG_XFRM
 static inline int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
Index: alloc_percpu-2.6.13/net/bridge/br_netfilter.c
===================================================================
--- alloc_percpu-2.6.13.orig/net/bridge/br_netfilter.c	2005-09-12 12:23:37.000000000 -0700
+++ alloc_percpu-2.6.13/net/bridge/br_netfilter.c	2005-09-12 12:24:01.000000000 -0700
@@ -85,7 +85,6 @@
 static struct rtable __fake_rtable = {
 	.u = {
 		.dst = {
-			.__refcnt		= ATOMIC_INIT(1),
 			.dev			= &__fake_net_device,
 			.path			= &__fake_rtable.u.dst,
 			.metrics		= {[RTAX_MTU - 1] = 1500},
@@ -1010,6 +1009,10 @@
 {
 	int i;
 
+	if (dst_init_rtu_array(&__fake_rtable.u.dst) < 0)
+		panic("br_netfilter : cannot allocate memory for dst-entry rtu array");
+	dst_refcnt_one(&__fake_rtable.u.dst);
+
 	for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) {
 		int ret;
 
@@ -1046,4 +1049,5 @@
 #ifdef CONFIG_SYSCTL
 	unregister_sysctl_table(brnf_sysctl_header);
 #endif
+	dst_free_rtu_array(&__fake_rtable.u.dst);
 }
Index: alloc_percpu-2.6.13/net/core/dst.c
===================================================================
--- alloc_percpu-2.6.13.orig/net/core/dst.c	2005-09-12 12:23:37.000000000 -0700
+++ alloc_percpu-2.6.13/net/core/dst.c	2005-09-12 12:24:01.000000000 -0700
@@ -131,9 +131,9 @@
 	if (!dst)
 		return NULL;
 	memset(dst, 0, ops->entry_size);
-	atomic_set(&dst->__refcnt, 0);
+	if (dst_init_rtu_array(dst) < 0)
+		return NULL;
 	dst->ops = ops;
-	dst->lastuse = jiffies;
 	dst->path = dst;
 	dst->input = dst_discard_in;
 	dst->output = dst_discard_out;
@@ -200,6 +200,7 @@
 #if RT_CACHE_DEBUG >= 2 
 	atomic_dec(&dst_total);
 #endif
+	dst_free_rtu_array(dst);
 	kmem_cache_free(dst->ops->kmem_cachep, dst);
 
 	dst = child;
Index: alloc_percpu-2.6.13/net/decnet/dn_route.c
===================================================================
--- alloc_percpu-2.6.13.orig/net/decnet/dn_route.c	2005-09-12 12:23:37.000000000 -0700
+++ alloc_percpu-2.6.13/net/decnet/dn_route.c	2005-09-12 12:24:01.000000000 -0700
@@ -77,6 +77,7 @@
 #include <linux/netfilter_decnet.h>
 #include <linux/rcupdate.h>
 #include <linux/times.h>
+#include <linux/cpu.h>
 #include <asm/errno.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
@@ -157,7 +158,29 @@
 
 static inline int dn_dst_useful(struct dn_route *rth, unsigned long now, unsigned long expire)
 {
+#ifdef CONFIG_NUMA
+	{
+		int max, sum = 0, age, cpu;
+		struct dst_entry *dst = &rth->u.dst;
+
+		cpu = dst->s_cpu;
+		max = cpu + NR_CPUS;
+		for(sum = 0; cpu < max; cpu++) {
+			int cpu_ = cpu % NR_CPUS;
+			if (cpu_online(cpu_)) {
+				sum += per_cpu_ptr(dst->pcc, cpu_)->refcnt;
+				age = now - per_cpu_ptr(dst->pcc, cpu_)->lastuse;
+				if (age <= expire) {
+					dst->s_cpu = cpu_ ;
+					return 1;
+				}
+			}
+		}
+		return (sum != 0);
+	}
+#else
 	return  (atomic_read(&rth->u.dst.__refcnt) || (now - rth->u.dst.lastuse) < expire) ;
+#endif
 }
 
 static void dn_dst_check_expire(unsigned long dummy)
@@ -1766,6 +1789,43 @@
 
 #endif /* CONFIG_PROC_FS */
 
+#if defined(CONFIG_NUMA) && defined(CONFIG_HOTPLUG_CPU)
+static int __devinit dn_rtcache_cpu_callback(struct notifier_block *nfb,
+                                   unsigned long action,
+                                   void *hcpu)
+{
+	int cpu = (int) hcpu;
+
+	switch(action) {
+		int i;
+		struct dn_route *rt, *next;
+
+		case CPU_DEAD:
+
+		for(i = 0; i < dn_rt_hash_mask; i++) {
+			spin_lock_bh(&dn_rt_hash_table[i].lock);
+
+			if ((rt = dn_rt_hash_table[i].chain) == NULL)
+				goto nothing_to_do;
+
+			for(; rt; rt=next) {
+				dst_ref_xfr_cpu_down(&rt->u.dst, cpu);
+				next = rt->u.rt_next;
+			}
+nothing_to_do:
+			spin_unlock_bh(&dn_rt_hash_table[i].lock);
+		}
+
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block dn_rtcache_cpu_notifier =
+			{ &dn_rtcache_cpu_callback, NULL, 0 };
+
+#endif
+
 void __init dn_route_init(void)
 {
 	int i, goal, order;
@@ -1822,10 +1882,16 @@
         dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
 
 	proc_net_fops_create("decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
+#if	defined(CONFIG_NUMA) && defined(CONFIG_HOTPLUG_CPU)
+	register_cpu_notifier(&dn_rtcache_cpu_notifier);
+#endif
 }
 
 void __exit dn_route_cleanup(void)
 {
+#if defined(CONFIG_NUMA) && defined(CONFIG_HOTPLUG_CPU)
+	unregister_cpu_notifier(&dn_rtcache_cpu_notifier);
+#endif
 	del_timer(&dn_route_timer);
 	dn_run_flush(0);
 
Index: alloc_percpu-2.6.13/net/ipv4/route.c
===================================================================
--- alloc_percpu-2.6.13.orig/net/ipv4/route.c	2005-09-12 12:23:37.000000000 -0700
+++ alloc_percpu-2.6.13/net/ipv4/route.c	2005-09-12 12:24:01.000000000 -0700
@@ -92,6 +92,7 @@
 #include <linux/jhash.h>
 #include <linux/rcupdate.h>
 #include <linux/times.h>
+#include <linux/cpu.h>
 #include <net/protocol.h>
 #include <net/ip.h>
 #include <net/route.h>
@@ -507,6 +508,54 @@
 		rth->u.dst.expires;
 }
 
+#ifdef CONFIG_NUMA
+
+/*
+ * For NUMA systems, we do not want to sum up all local cpu refcnts every
+ * time. So we consider lastuse element of the dst_entry and start loop
+ * with the cpu where this entry was allocated. If dst_entry is not timed
+ * out then update s_cpu of this dst_entry so that next time we can start from
+ * that cpu.
+ */
+static inline int rt_check_age(struct rtable *rth,
+			unsigned long tmo1, unsigned long tmo2)
+{
+	int max, sum = 0, age, idx;
+	struct dst_entry *dst = &rth->u.dst;
+	unsigned long now = jiffies;
+
+	idx = dst->s_cpu;
+	max = idx + NR_CPUS;
+	for(sum = 0; idx < max; idx++) {
+		int cpu_ = idx % NR_CPUS;
+		if (cpu_online(cpu_)) {
+			sum += per_cpu_ptr(dst->pcc, cpu_)->refcnt;
+			age = now - per_cpu_ptr(dst->pcc, cpu_)->lastuse;
+			if ((age <= tmo1 && !rt_fast_clean(rth)) ||
+					(age <= tmo2 && rt_valuable(rth))) {
+				dst->s_cpu = cpu_ ;
+				return 0;
+			}
+		}
+	}
+	return (sum == 0);
+}
+
+/*
+ * In this function order of examining three factors (ref_cnt, expires,
+ * lastuse) is changed, considering the cost of analyzing refcnt and lastuse
+ * which are localized for each cpu on NUMA.
+ */
+static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2)
+{
+	if (rth->u.dst.expires && time_after_eq(jiffies, rth->u.dst.expires))
+		return (dst_refcnt(&rth->u.dst) == 0) ;
+
+	return rt_check_age(rth, tmo1, tmo2);
+}
+
+#else
+
 static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2)
 {
 	unsigned long age;
@@ -529,6 +578,8 @@
 out:	return ret;
 }
 
+#endif
+
 /* Bits of score are:
  * 31: very valuable
  * 30: not quite useless
@@ -1108,8 +1159,19 @@
 
 void ip_rt_copy(struct rtable *to, struct rtable *from)
 {
+#ifdef CONFIG_NUMA
+	struct per_cpu_cnt *tmp_pnc;
+	tmp_pnc = to->u.dst.pcc;
+
+	*to = *from;
+	to->u.dst.pcc = tmp_pnc;
+	per_cpu_ptr(to->u.dst.pcc,get_cpu())->use = 1;
+	to->u.dst.s_cpu = smp_processor_id();
+	put_cpu();
+#else
 	*to = *from;
 	to->u.dst.__use 	= 1;
+#endif
 }
 
 void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
@@ -3108,6 +3170,33 @@
 }
 __setup("rhash_entries=", set_rhash_entries);
 
+#if defined(CONFIG_NUMA) && defined(CONFIG_HOTPLUG_CPU)
+static int __devinit rtcache_cpu_callback(struct notifier_block *nfb,
+                                   unsigned long action,
+				   void *hcpu)
+{
+	int cpu = (int) hcpu;
+
+	switch(action) {
+		int i ;
+		struct rtable *rth;
+		case CPU_DEAD:
+			for(i = rt_hash_mask; i >= 0; i--) {
+				spin_lock_irq(rt_hash_lock_addr(i));
+				rth = rt_hash_table[i].chain;
+				while(rth) {
+					dst_ref_xfr_cpu_down(&rth->u.dst, cpu);
+					rth = rth->u.rt_next;
+				}
+				spin_unlock_irq(rt_hash_lock_addr(i));
+			}
+			break;
+	}
+	return NOTIFY_OK;
+}
+static struct notifier_block rtcache_cpu_notifier = { &rtcache_cpu_callback, NULL, 0 };
+#endif
+
 int __init ip_rt_init(void)
 {
 	int rc = 0;
@@ -3197,6 +3286,9 @@
 	xfrm_init();
 	xfrm4_init();
 #endif
+#if defined(CONFIG_NUMA) && defined(CONFIG_HOTPLUG_CPU)
+	register_cpu_notifier(&rtcache_cpu_notifier);
+#endif
 	return rc;
 }
 
Index: alloc_percpu-2.6.13/net/ipv6/ip6_fib.c
===================================================================
--- alloc_percpu-2.6.13.orig/net/ipv6/ip6_fib.c	2005-09-12 12:23:37.000000000 -0700
+++ alloc_percpu-2.6.13/net/ipv6/ip6_fib.c	2005-09-12 12:24:01.000000000 -0700
@@ -1209,6 +1209,35 @@
 	spin_unlock_bh(&fib6_gc_lock);
 }
 
+#if defined(CONFIG_NUMA) && defined(CONFIG_HOTPLUG_CPU)
+#include <linux/cpu.h>
+inline static int rt6_ref_xfr_cpu_down(struct rt6_info *rt, void *arg)
+{
+	dst_ref_xfr_cpu_down(&rt->u.dst, (int)arg);
+	return 0;
+}
+
+static int __devinit ipv6_rtcache_cpu_callback(struct notifier_block *nfb,
+                                   unsigned long action,
+                                   void *hcpu)
+{
+	int cpu = (int) hcpu;
+
+	switch(action) {
+		case CPU_DEAD:
+			write_lock_bh(&rt6_lock);
+			fib6_clean_tree(&ip6_routing_table, rt6_ref_xfr_cpu_down,
+					0, (void *)cpu);
+			write_unlock_bh(&rt6_lock);
+			break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block ipv6_rtcache_cpu_notifier =
+				{ &ipv6_rtcache_cpu_callback, NULL, 0 };
+#endif
+
 void __init fib6_init(void)
 {
 	fib6_node_kmem = kmem_cache_create("fib6_nodes",
@@ -1217,10 +1246,16 @@
 					   NULL, NULL);
 	if (!fib6_node_kmem)
 		panic("cannot create fib6_nodes cache");
+#if defined(CONFIG_NUMA) && defined(CONFIG_HOTPLUG_CPU)
+	register_cpu_notifier(&ipv6_rtcache_cpu_notifier);
+#endif
 }
 
 void fib6_gc_cleanup(void)
 {
+#if defined(CONFIG_NUMA) && defined(CONFIG_HOTPLUG_CPU)
+	unregister_cpu_notifier(&ipv6_rtcache_cpu_notifier);
+#endif
 	del_timer(&ip6_fib_timer);
 	kmem_cache_destroy(fib6_node_kmem);
 }
Index: alloc_percpu-2.6.13/net/ipv6/route.c
===================================================================
--- alloc_percpu-2.6.13.orig/net/ipv6/route.c	2005-09-12 12:23:37.000000000 -0700
+++ alloc_percpu-2.6.13/net/ipv6/route.c	2005-09-12 12:24:01.000000000 -0700
@@ -110,8 +110,6 @@
 struct rt6_info ip6_null_entry = {
 	.u = {
 		.dst = {
-			.__refcnt	= ATOMIC_INIT(1),
-			.__use		= 1,
 			.dev		= &loopback_dev,
 			.obsolete	= -1,
 			.error		= -ENETUNREACH,
@@ -2104,6 +2102,10 @@
 						     NULL, NULL);
 	if (!ip6_dst_ops.kmem_cachep)
 		panic("cannot create ip6_dst_cache");
+	if (dst_init_rtu_array(&ip6_null_entry.u.dst) < 0)
+		panic("ip6_route : can't allocate memory for dst-entry array");
+	dst_use_inc(&ipv6_null_entry.u.dist);
+	dst_refcnt_one(&ip6_null_entry.u.dst);
 
 	fib6_init();
 #ifdef 	CONFIG_PROC_FS
@@ -2130,4 +2132,5 @@
 	rt6_ifdown(NULL);
 	fib6_gc_cleanup();
 	kmem_cache_destroy(ip6_dst_ops.kmem_cachep);
+	dst_free_rtu_array(&ip6_null_entry.u.dst);
 }

^ permalink raw reply

* [patch 8/11] net: dst_abstraction macros
From: Ravikiran G Thirumalai @ 2005-09-13 16:12 UTC (permalink / raw)
  To: Andrew Morton
  Cc: linux-kernel, dipankar, bharata, shai, Rusty Russell, netdev,
	davem
In-Reply-To: <20050913155112.GB3570@localhost.localdomain>

This patch introduces macros to handle the use, lastuse and refcnt fields in
the dst_entry structure using macros. Having macros manipulate these fields
allows cleaner source code and provides an easy way for modifications to the
way these performance critical fields are handled.

The introduction of macros removes some code that is repeated in 
various places. Also

- decnet_dn_route: introduces dn_dst_useful to check the usefulness of a dst
		entry. dst_update_rtu used to reduce code duplication.

- net/ipv4/route.c: add ip_rt_copy. dst_update_rtu used to reduce code duplication.

The patch is a prerequisite for the dst numa patch. 

Signed-off-by: Pravin B. Shelar <pravins@calsoftinc.com>
Signed-off-by: Shobhit Dayal <shobhit@calsoftinc.com>
Signed-off-by: Shai Fultheim <shai@scalex86.org>
Signed-off-by: Christoph Lameter <christoph@lameter.com>
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>

Index: alloc_percpu-2.6.13-rc6/include/net/dst.h
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/include/net/dst.h	2005-08-15 17:54:34.721623250 -0400
+++ alloc_percpu-2.6.13-rc6/include/net/dst.h	2005-08-15 17:58:14.499358500 -0400
@@ -103,6 +103,30 @@
 
 #ifdef __KERNEL__
 
+#define dst_use(__dst) (__dst)->__use
+#define dst_use_inc(__dst) (__dst)->__use++
+
+#define dst_lastuse(__dst) (__dst)->lastuse
+#define dst_lastuse_set(__dst) (__dst)->lastuse = jiffies
+
+#define dst_update_tu(__dst) do { dst_lastuse_set(__dst);dst_use_inc(__dst); } while (0)
+#define dst_update_rtu(__dst) do { dst_lastuse_set(__dst);dst_hold(__dst);dst_use_inc(__dst); } while (0)
+
+#define dst_refcnt(__dst) atomic_read(&(__dst)->__refcnt)
+#define dst_refcnt_one(__dst) atomic_set(&(__dst)->__refcnt, 1)
+#define dst_refcnt_dec(__dst) atomic_dec(&(__dst)->__refcnt)
+#define dst_hold(__dst) atomic_inc(&(__dst)->__refcnt)
+
+static inline
+void dst_release(struct dst_entry * dst)
+{
+	if (dst) {
+		WARN_ON(dst_refcnt(dst) < 1);
+		smp_mb__before_atomic_dec();
+		dst_refcnt_dec(dst);
+	}
+}
+
 static inline u32
 dst_metric(const struct dst_entry *dst, int metric)
 {
@@ -134,29 +158,14 @@
 	return dst_metric(dst, RTAX_LOCK) & (1<<metric);
 }
 
-static inline void dst_hold(struct dst_entry * dst)
-{
-	atomic_inc(&dst->__refcnt);
-}
-
 static inline
 struct dst_entry * dst_clone(struct dst_entry * dst)
 {
 	if (dst)
-		atomic_inc(&dst->__refcnt);
+		dst_hold(dst);
 	return dst;
 }
 
-static inline
-void dst_release(struct dst_entry * dst)
-{
-	if (dst) {
-		WARN_ON(atomic_read(&dst->__refcnt) < 1);
-		smp_mb__before_atomic_dec();
-		atomic_dec(&dst->__refcnt);
-	}
-}
-
 /* Children define the path of the packet through the
  * Linux networking.  Thus, destinations are stackable.
  */
@@ -177,7 +186,7 @@
 {
 	if (dst->obsolete > 1)
 		return;
-	if (!atomic_read(&dst->__refcnt)) {
+	if (!dst_refcnt(dst)) {
 		dst = dst_destroy(dst);
 		if (!dst)
 			return;
Index: alloc_percpu-2.6.13-rc6/net/core/dst.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/core/dst.c	2005-08-15 17:54:34.761625750 -0400
+++ alloc_percpu-2.6.13-rc6/net/core/dst.c	2005-08-15 17:58:14.499358500 -0400
@@ -57,7 +57,7 @@
 	dstp = &dst_garbage_list;
 	work_performed = 0;
 	while ((dst = *dstp) != NULL) {
-		if (atomic_read(&dst->__refcnt)) {
+		if (dst_refcnt(dst)) {
 			dstp = &dst->next;
 			delayed++;
 			continue;
@@ -176,9 +176,8 @@
 	struct neighbour *neigh;
 	struct hh_cache *hh;
 
-	smp_rmb();
-
 again:
+	smp_rmb();
 	neigh = dst->neighbour;
 	hh = dst->hh;
 	child = dst->child;
@@ -206,16 +205,16 @@
 	dst = child;
 	if (dst) {
 		int nohash = dst->flags & DST_NOHASH;
-
-		if (atomic_dec_and_test(&dst->__refcnt)) {
-			/* We were real parent of this dst, so kill child. */
-			if (nohash)
+		dst_refcnt_dec(dst);
+		if (nohash) {
+			if (!dst_refcnt(dst)) {
+				/* We were real parent of this dst, so kill child. */
 				goto again;
-		} else {
-			/* Child is still referenced, return it for freeing. */
-			if (nohash)
+			} else {
+				/* Child is still referenced, return it for freeing. */
 				return dst;
-			/* Child is still in his hash table */
+				/* Child is still in his hash table */
+			}
 		}
 	}
 	return NULL;
Index: alloc_percpu-2.6.13-rc6/net/decnet/dn_route.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/decnet/dn_route.c	2005-08-15 17:54:34.789627500 -0400
+++ alloc_percpu-2.6.13-rc6/net/decnet/dn_route.c	2005-08-15 17:58:14.503358750 -0400
@@ -155,6 +155,11 @@
 	call_rcu_bh(&rt->u.dst.rcu_head, dst_rcu_free);
 }
 
+static inline int dn_dst_useful(struct dn_route *rth, unsigned long now, unsigned long expire)
+{
+	return  (atomic_read(&rth->u.dst.__refcnt) || (now - rth->u.dst.lastuse) < expire) ;
+}
+
 static void dn_dst_check_expire(unsigned long dummy)
 {
 	int i;
@@ -167,8 +172,7 @@
 
 		spin_lock(&dn_rt_hash_table[i].lock);
 		while((rt=*rtp) != NULL) {
-			if (atomic_read(&rt->u.dst.__refcnt) ||
-					(now - rt->u.dst.lastuse) < expire) {
+			if (dn_dst_useful(rt, now, expire)) {
 				rtp = &rt->u.rt_next;
 				continue;
 			}
@@ -198,8 +202,7 @@
 		rtp = &dn_rt_hash_table[i].chain;
 
 		while((rt=*rtp) != NULL) {
-			if (atomic_read(&rt->u.dst.__refcnt) ||
-					(now - rt->u.dst.lastuse) < expire) {
+			if (dn_dst_useful(rt, now, expire)) {
 				rtp = &rt->u.rt_next;
 				continue;
 			}
@@ -277,10 +280,8 @@
 static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp)
 {
 	struct dn_route *rth, **rthp;
-	unsigned long now = jiffies;
-
-	rthp = &dn_rt_hash_table[hash].chain;
 
+ 	rthp = &dn_rt_hash_table[hash].chain;
 	spin_lock_bh(&dn_rt_hash_table[hash].lock);
 	while((rth = *rthp) != NULL) {
 		if (compare_keys(&rth->fl, &rt->fl)) {
@@ -290,9 +291,7 @@
 					   dn_rt_hash_table[hash].chain);
 			rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
 
-			rth->u.dst.__use++;
-			dst_hold(&rth->u.dst);
-			rth->u.dst.lastuse = now;
+			dst_update_rtu(&rth->u.dst);
 			spin_unlock_bh(&dn_rt_hash_table[hash].lock);
 
 			dnrt_drop(rt);
@@ -304,10 +303,8 @@
 
 	rcu_assign_pointer(rt->u.rt_next, dn_rt_hash_table[hash].chain);
 	rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
-	
-	dst_hold(&rt->u.dst);
-	rt->u.dst.__use++;
-	rt->u.dst.lastuse = now;
+
+	dst_update_rtu(&rt->u.dst);
 	spin_unlock_bh(&dn_rt_hash_table[hash].lock);
 	*rp = rt;
 	return 0;
@@ -1091,7 +1088,7 @@
 	if (rt == NULL)
 		goto e_nobufs;
 
-	atomic_set(&rt->u.dst.__refcnt, 1);
+	dst_refcnt_one(&rt->u.dst);
 	rt->u.dst.flags   = DST_HOST;
 
 	rt->fl.fld_src    = oldflp->fld_src;
@@ -1115,7 +1112,7 @@
 	rt->u.dst.neighbour = neigh;
 	neigh = NULL;
 
-	rt->u.dst.lastuse = jiffies;
+	dst_lastuse_set(&rt->u.dst);
 	rt->u.dst.output  = dn_output;
 	rt->u.dst.input   = dn_rt_bug;
 	rt->rt_flags      = flags;
@@ -1173,9 +1170,7 @@
 #endif
 			    (rt->fl.iif == 0) &&
 			    (rt->fl.oif == flp->oif)) {
-				rt->u.dst.lastuse = jiffies;
-				dst_hold(&rt->u.dst);
-				rt->u.dst.__use++;
+				dst_update_rtu(&rt->u.dst);
 				rcu_read_unlock_bh();
 				*pprt = &rt->u.dst;
 				return 0;
@@ -1381,7 +1376,7 @@
 	rt->u.dst.flags = DST_HOST;
 	rt->u.dst.neighbour = neigh;
 	rt->u.dst.dev = out_dev;
-	rt->u.dst.lastuse = jiffies;
+	dst_lastuse_set(&rt->u.dst);
 	rt->u.dst.output = dn_rt_bug;
 	switch(res.type) {
 		case RTN_UNICAST:
@@ -1452,9 +1447,7 @@
 		    (rt->fl.fld_fwmark == skb->nfmark) &&
 #endif
 		    (rt->fl.iif == cb->iif)) {
-			rt->u.dst.lastuse = jiffies;
-			dst_hold(&rt->u.dst);
-			rt->u.dst.__use++;
+			dst_update_rtu(&rt->u.dst);
 			rcu_read_unlock();
 			skb->dst = (struct dst_entry *)rt;
 			return 0;
@@ -1504,9 +1497,9 @@
 		RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway);
 	if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
 		goto rtattr_failure;
-	ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
-	ci.rta_used     = rt->u.dst.__use;
-	ci.rta_clntref  = atomic_read(&rt->u.dst.__refcnt);
+	ci.rta_lastuse = jiffies_to_clock_t(jiffies - dst_lastuse(&rt->u.dst));
+	ci.rta_used     =  dst_use(&rt->u.dst);
+	ci.rta_clntref  = dst_refcnt(&rt->u.dst);
 	if (rt->u.dst.expires)
 		ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies);
 	else
@@ -1729,8 +1722,8 @@
 			rt->u.dst.dev ? rt->u.dst.dev->name : "*",
 			dn_addr2asc(dn_ntohs(rt->rt_daddr), buf1),
 			dn_addr2asc(dn_ntohs(rt->rt_saddr), buf2),
-			atomic_read(&rt->u.dst.__refcnt),
-			rt->u.dst.__use,
+			dst_refcnt(&rt->u.dst),
+			dst_use(&rt->u.dst),
 			(int) dst_metric(&rt->u.dst, RTAX_RTT));
 	return 0;
 } 
Index: alloc_percpu-2.6.13-rc6/net/ipv4/ipvs/ip_vs_xmit.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv4/ipvs/ip_vs_xmit.c	2005-08-15 17:54:34.837630500 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv4/ipvs/ip_vs_xmit.c	2005-08-15 17:55:23.980701750 -0400
@@ -88,7 +88,7 @@
 			__ip_vs_dst_set(dest, rtos, dst_clone(&rt->u.dst));
 			IP_VS_DBG(10, "new dst %u.%u.%u.%u, refcnt=%d, rtos=%X\n",
 				  NIPQUAD(dest->addr),
-				  atomic_read(&rt->u.dst.__refcnt), rtos);
+				  dst_refcnt(&rt->u.dst), rtos);
 		}
 		spin_unlock(&dest->dst_lock);
 	} else {
Index: alloc_percpu-2.6.13-rc6/net/ipv4/multipath_drr.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv4/multipath_drr.c	2005-08-15 17:54:34.905634750 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv4/multipath_drr.c	2005-08-15 17:55:23.980701750 -0400
@@ -149,8 +149,7 @@
 		    multipath_comparekeys(&nh->fl, flp)) {
 			int nh_ifidx = nh->u.dst.dev->ifindex;
 
-			nh->u.dst.lastuse = jiffies;
-			nh->u.dst.__use++;
+			dst_update_tu(&nh->u.dst);
 			if (result != NULL)
 				continue;
 
Index: alloc_percpu-2.6.13-rc6/net/ipv4/multipath_random.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv4/multipath_random.c	2005-08-15 17:54:34.909635000 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv4/multipath_random.c	2005-08-15 17:55:23.980701750 -0400
@@ -94,7 +94,8 @@
 		for (rt = first; rt; rt = rt->u.rt_next) {
 			if ((rt->u.dst.flags & DST_BALANCED) != 0 &&
 			    multipath_comparekeys(&rt->fl, flp)) {
-				rt->u.dst.lastuse = jiffies;
+
+				dst_lastuse_set(&rt->u.dst);
 
 				if (i == candidate_no)
 					decision = rt;
@@ -107,7 +108,7 @@
 		}
 	}
 
-	decision->u.dst.__use++;
+	dst_use_inc(&decision->u.dst);
 	*rp = decision;
 }
 
Index: alloc_percpu-2.6.13-rc6/net/ipv4/multipath_rr.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv4/multipath_rr.c	2005-08-15 17:54:34.973639000 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv4/multipath_rr.c	2005-08-15 17:55:24.056706500 -0400
@@ -62,10 +62,11 @@
  	     nh = rcu_dereference(nh->u.rt_next)) {
 		if ((nh->u.dst.flags & DST_BALANCED) != 0 &&
 		    multipath_comparekeys(&nh->fl, flp)) {
-			nh->u.dst.lastuse = jiffies;
+			int __use = dst_use(&nh->u.dst);
+			dst_lastuse_set(&nh->u.dst);
 
-			if (min_use == -1 || nh->u.dst.__use < min_use) {
-				min_use = nh->u.dst.__use;
+			if (min_use == -1 || __use < min_use) {
+				min_use = __use;
 				min_use_cand = nh;
 			}
 		}
@@ -74,7 +75,7 @@
 	if (!result)
 		result = first;
 
-	result->u.dst.__use++;
+	dst_use_inc(&result->u.dst);
 	*rp = result;
 }
 
Index: alloc_percpu-2.6.13-rc6/net/ipv4/multipath_wrandom.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv4/multipath_wrandom.c	2005-08-15 17:54:34.973639000 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv4/multipath_wrandom.c	2005-08-15 17:55:24.056706500 -0400
@@ -202,7 +202,7 @@
 	decision = first;
 	last_mpc = NULL;
 	for (mpc = first_mpc; mpc; mpc = mpc->next) {
-		mpc->rt->u.dst.lastuse = jiffies;
+		dst_lastuse_set(&mpc->rt->u.dst);
 		if (last_power <= selector && selector < mpc->power)
 			decision = mpc->rt;
 
@@ -217,8 +217,7 @@
 		/* concurrent __multipath_flush may lead to !last_mpc */
 		kfree(last_mpc);
 	}
-
-	decision->u.dst.__use++;
+	dst_use_inc(&decision->u.dst);
 	*rp = decision;
 }
 
Index: alloc_percpu-2.6.13-rc6/net/ipv4/route.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv4/route.c	2005-08-15 17:54:34.973639000 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv4/route.c	2005-08-15 17:58:14.503358750 -0400
@@ -334,8 +334,8 @@
 			      "%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
 			r->u.dst.dev ? r->u.dst.dev->name : "*",
 			(unsigned long)r->rt_dst, (unsigned long)r->rt_gateway,
-			r->rt_flags, atomic_read(&r->u.dst.__refcnt),
-			r->u.dst.__use, 0, (unsigned long)r->rt_src,
+			r->rt_flags, dst_refcnt(&r->u.dst),
+			dst_use(&r->u.dst), 0, (unsigned long)r->rt_src,
 			(dst_metric(&r->u.dst, RTAX_ADVMSS) ?
 			     (int)dst_metric(&r->u.dst, RTAX_ADVMSS) + 40 : 0),
 			dst_metric(&r->u.dst, RTAX_WINDOW),
@@ -512,7 +512,7 @@
 	unsigned long age;
 	int ret = 0;
 
-	if (atomic_read(&rth->u.dst.__refcnt))
+	if (dst_refcnt(&rth->u.dst))
 		goto out;
 
 	ret = 1;
@@ -536,7 +536,7 @@
  */
 static inline u32 rt_score(struct rtable *rt)
 {
-	u32 score = jiffies - rt->u.dst.lastuse;
+	u32 score = jiffies - dst_lastuse(&rt->u.dst);
 
 	score = ~score & ~(3<<30);
 
@@ -943,9 +943,7 @@
 			 */
 			rcu_assign_pointer(rt_hash_table[hash].chain, rth);
 
-			rth->u.dst.__use++;
-			dst_hold(&rth->u.dst);
-			rth->u.dst.lastuse = now;
+			dst_update_rtu(&rth->u.dst);
 			spin_unlock_bh(rt_hash_lock_addr(hash));
 
 			rt_drop(rt);
@@ -953,7 +951,7 @@
 			return 0;
 		}
 
-		if (!atomic_read(&rth->u.dst.__refcnt)) {
+		if (!dst_refcnt(&rth->u.dst)) {
 			u32 score = rt_score(rth);
 
 			if (score <= min_score) {
@@ -1108,6 +1106,12 @@
 	spin_unlock_bh(rt_hash_lock_addr(hash));
 }
 
+void ip_rt_copy(struct rtable *to, struct rtable *from)
+{
+	*to = *from;
+	to->u.dst.__use 	= 1;
+}
+
 void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
 		    u32 saddr, u8 tos, struct net_device *dev)
 {
@@ -1175,17 +1179,17 @@
 				}
 
 				/* Copy all the information. */
-				*rt = *rth;
- 				INIT_RCU_HEAD(&rt->u.dst.rcu_head);
-				rt->u.dst.__use		= 1;
-				atomic_set(&rt->u.dst.__refcnt, 1);
+				ip_rt_copy(rt, rth);
+
+				INIT_RCU_HEAD(&rt->u.dst.rcu_head);
+				dst_lastuse_set(&rt->u.dst);
+				dst_refcnt_one(&rt->u.dst);
 				rt->u.dst.child		= NULL;
 				if (rt->u.dst.dev)
 					dev_hold(rt->u.dst.dev);
 				if (rt->idev)
 					in_dev_hold(rt->idev);
 				rt->u.dst.obsolete	= 0;
-				rt->u.dst.lastuse	= jiffies;
 				rt->u.dst.path		= &rt->u.dst;
 				rt->u.dst.neighbour	= NULL;
 				rt->u.dst.hh		= NULL;
@@ -1619,7 +1623,7 @@
 
 	rth->u.dst.output= ip_rt_bug;
 
-	atomic_set(&rth->u.dst.__refcnt, 1);
+	dst_refcnt_one(&rth->u.dst);
 	rth->u.dst.flags= DST_HOST;
 	if (in_dev->cnf.no_policy)
 		rth->u.dst.flags |= DST_NOPOLICY;
@@ -1818,7 +1822,7 @@
 	err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth);
 	if (err)
 		return err;
-	atomic_set(&rth->u.dst.__refcnt, 1);
+	dst_refcnt_one(&rth->u.dst);
 
 	/* put it into the cache */
 	hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos);
@@ -1876,7 +1880,7 @@
 		 * outside
 		 */
 		if (hop == lasthop)
-			atomic_set(&(skb->dst->__refcnt), 1);
+			dst_refcnt_one(skb->dst);
 	}
 	return err;
 #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED  */
@@ -2012,7 +2016,7 @@
 
 	rth->u.dst.output= ip_rt_bug;
 
-	atomic_set(&rth->u.dst.__refcnt, 1);
+	dst_refcnt_one(&rth->u.dst);
 	rth->u.dst.flags= DST_HOST;
 	if (in_dev->cnf.no_policy)
 		rth->u.dst.flags |= DST_NOPOLICY;
@@ -2102,9 +2106,7 @@
 		    rth->fl.fl4_fwmark == skb->nfmark &&
 #endif
 		    rth->fl.fl4_tos == tos) {
-			rth->u.dst.lastuse = jiffies;
-			dst_hold(&rth->u.dst);
-			rth->u.dst.__use++;
+			dst_update_rtu(&rth->u.dst);
 			RT_CACHE_STAT_INC(in_hit);
 			rcu_read_unlock();
 			skb->dst = (struct dst_entry*)rth;
@@ -2288,7 +2290,7 @@
 	if (err == 0) {
 		u32 tos = RT_FL_TOS(oldflp);
 
-		atomic_set(&rth->u.dst.__refcnt, 1);
+		dst_refcnt_one(&rth->u.dst);
 		
 		hash = rt_hash_code(oldflp->fl4_dst, 
 				    oldflp->fl4_src ^ (oldflp->oif << 5), tos);
@@ -2348,7 +2350,7 @@
 			if (err != 0)
 				return err;
 		}
-		atomic_set(&(*rp)->u.dst.__refcnt, 1);
+		dst_refcnt_one(&(*rp)->u.dst);
 		return err;
 	} else {
 		return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out,
@@ -2584,10 +2586,7 @@
 				rcu_read_unlock_bh();
 				return 0;
 			}
-
-			rth->u.dst.lastuse = jiffies;
-			dst_hold(&rth->u.dst);
-			rth->u.dst.__use++;
+			dst_update_rtu(&rth->u.dst);
 			RT_CACHE_STAT_INC(out_hit);
 			rcu_read_unlock_bh();
 			*rp = rth;
@@ -2673,9 +2672,9 @@
 		RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway);
 	if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
 		goto rtattr_failure;
-	ci.rta_lastuse	= jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
-	ci.rta_used	= rt->u.dst.__use;
-	ci.rta_clntref	= atomic_read(&rt->u.dst.__refcnt);
+	ci.rta_lastuse	= jiffies_to_clock_t(jiffies - dst_lastuse(&rt->u.dst));
+	ci.rta_used	= dst_use(&rt->u.dst);
+	ci.rta_clntref	= dst_refcnt(&rt->u.dst);
 	if (rt->u.dst.expires)
 		ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies);
 	else
Index: alloc_percpu-2.6.13-rc6/net/ipv4/xfrm4_policy.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv4/xfrm4_policy.c	2005-08-15 17:54:34.973639000 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv4/xfrm4_policy.c	2005-08-15 17:55:24.060706750 -0400
@@ -135,7 +135,7 @@
 			dev_hold(rt->u.dst.dev);
 		dst_prev->obsolete	= -1;
 		dst_prev->flags	       |= DST_HOST;
-		dst_prev->lastuse	= jiffies;
+		dst_lastuse_set(dst_prev);
 		dst_prev->header_len	= header_len;
 		dst_prev->trailer_len	= trailer_len;
 		memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
Index: alloc_percpu-2.6.13-rc6/net/ipv6/ip6_fib.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv6/ip6_fib.c	2005-08-15 17:54:34.973639000 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv6/ip6_fib.c	2005-08-15 17:58:14.503358750 -0400
@@ -1160,8 +1160,8 @@
 		}
 		gc_args.more++;
 	} else if (rt->rt6i_flags & RTF_CACHE) {
-		if (atomic_read(&rt->u.dst.__refcnt) == 0 &&
-		    time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) {
+		if (dst_refcnt(&rt->u.dst) == 0 &&
+		    time_after_eq(now, dst_lastuse(&rt->u.dst) + gc_args.timeout)) {
 			RT6_TRACE("aging clone %p\n", rt);
 			return -1;
 		} else if ((rt->rt6i_flags & RTF_GATEWAY) &&
Index: alloc_percpu-2.6.13-rc6/net/ipv6/route.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv6/route.c	2005-08-15 17:54:34.973639000 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv6/route.c	2005-08-15 17:58:14.507359000 -0400
@@ -368,10 +368,9 @@
 	fn = fib6_lookup(&ip6_routing_table, daddr, saddr);
 	rt = rt6_device_match(fn->leaf, oif, strict);
 	dst_hold(&rt->u.dst);
-	rt->u.dst.__use++;
-	read_unlock_bh(&rt6_lock);
 
-	rt->u.dst.lastuse = jiffies;
+	read_unlock_bh(&rt6_lock);
+	dst_update_tu(&rt->u.dst);
 	if (rt->u.dst.error == 0)
 		return rt;
 	dst_release(&rt->u.dst);
@@ -512,8 +511,7 @@
 out:
 	read_unlock_bh(&rt6_lock);
 out2:
-	rt->u.dst.lastuse = jiffies;
-	rt->u.dst.__use++;
+	dst_update_tu(&rt->u.dst);
 	skb->dst = (struct dst_entry *) rt;
 }
 
@@ -572,8 +570,7 @@
 out:
 	read_unlock_bh(&rt6_lock);
 out2:
-	rt->u.dst.lastuse = jiffies;
-	rt->u.dst.__use++;
+	dst_update_tu(&rt->u.dst);
 	return &rt->u.dst;
 }
 
@@ -685,7 +682,7 @@
 	rt->rt6i_dev	  = dev;
 	rt->rt6i_idev     = idev;
 	rt->rt6i_nexthop  = neigh;
-	atomic_set(&rt->u.dst.__refcnt, 1);
+	dst_refcnt_one(&rt->u.dst);
 	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
 	rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
 	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
@@ -719,7 +716,7 @@
 	pprev = &ndisc_dst_gc_list;
 	freed = 0;
 	while ((dst = *pprev) != NULL) {
-		if (!atomic_read(&dst->__refcnt)) {
+		if (!dst_refcnt(dst)) {
 			*pprev = dst->next;
 			dst_free(dst);
 			freed++;
@@ -1261,7 +1258,7 @@
 		rt->rt6i_idev = ort->rt6i_idev;
 		if (rt->rt6i_idev)
 			in6_dev_hold(rt->rt6i_idev);
-		rt->u.dst.lastuse = jiffies;
+		dst_lastuse_set(&rt->u.dst);
 		rt->rt6i_expires = 0;
 
 		ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway);
@@ -1424,7 +1421,7 @@
 	ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
 	rt->rt6i_dst.plen = 128;
 
-	atomic_set(&rt->u.dst.__refcnt, 1);
+	dst_refcnt_one(&rt->u.dst);
 
 	return rt;
 }
@@ -1637,13 +1634,13 @@
 	if (rt->u.dst.dev)
 		RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->rt6i_dev->ifindex);
 	RTA_PUT(skb, RTA_PRIORITY, 4, &rt->rt6i_metric);
-	ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse);
+	ci.rta_lastuse = jiffies_to_clock_t(jiffies - dst_lastuse(&rt->u.dst));
 	if (rt->rt6i_expires)
 		ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies);
 	else
 		ci.rta_expires = 0;
-	ci.rta_used = rt->u.dst.__use;
-	ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
+	ci.rta_used = dst_use(&rt->u.dst);
+	ci.rta_clntref = dst_refcnt(&rt->u.dst);
 	ci.rta_error = rt->u.dst.error;
 	ci.rta_id = 0;
 	ci.rta_ts = 0;
@@ -1927,8 +1924,8 @@
 	}
 	arg->len += sprintf(arg->buffer + arg->len,
 			    " %08x %08x %08x %08x %8s\n",
-			    rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt),
-			    rt->u.dst.__use, rt->rt6i_flags, 
+			    rt->rt6i_metric, dst_refcnt(&rt->u.dst),
+			    dst_use(&rt->u.dst), rt->rt6i_flags,
 			    rt->rt6i_dev ? rt->rt6i_dev->name : "");
 	return 0;
 }
Index: alloc_percpu-2.6.13-rc6/net/ipv6/xfrm6_policy.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/ipv6/xfrm6_policy.c	2005-08-15 17:54:34.977639250 -0400
+++ alloc_percpu-2.6.13-rc6/net/ipv6/xfrm6_policy.c	2005-08-15 17:55:24.160713000 -0400
@@ -156,7 +156,7 @@
 			dev_hold(rt->u.dst.dev);
 		dst_prev->obsolete	= -1;
 		dst_prev->flags	       |= DST_HOST;
-		dst_prev->lastuse	= jiffies;
+		dst_lastuse_set(dst_prev);
 		dst_prev->header_len	= header_len;
 		dst_prev->trailer_len	= trailer_len;
 		memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
Index: alloc_percpu-2.6.13-rc6/net/xfrm/xfrm_policy.c
===================================================================
--- alloc_percpu-2.6.13-rc6.orig/net/xfrm/xfrm_policy.c	2005-08-15 17:54:34.977639250 -0400
+++ alloc_percpu-2.6.13-rc6/net/xfrm/xfrm_policy.c	2005-08-15 17:55:24.184714500 -0400
@@ -1090,7 +1090,7 @@
 
 static int unused_bundle(struct dst_entry *dst)
 {
-	return !atomic_read(&dst->__refcnt);
+	return !dst_refcnt(dst);
 }
 
 static void __xfrm_garbage_collect(void)

^ permalink raw reply

* [patch 7/11] net: Use bigrefs for net_device.refcount
From: Ravikiran G Thirumalai @ 2005-09-13 16:10 UTC (permalink / raw)
  To: Andrew Morton
  Cc: linux-kernel, dipankar, bharata, shai, Rusty Russell, netdev,
	davem
In-Reply-To: <20050913155112.GB3570@localhost.localdomain>

The net_device has a refcnt used to keep track of it's uses.
This is used at the time of unregistering the network device
(module unloading ..) (see netdev_wait_allrefs) .
For loopback_dev , this refcnt increment/decrement  is causing
unnecessary traffic on the interlink for NUMA system
affecting it's performance.  This patch improves tbench numbers by 6% on a
8way x86 Xeon (x445).

This patch is dependent on the bigref patch 

Signed-off-by : Niraj Kumar <nirajk@calsoftinc.com>
Signed-off-by : Shai Fultheim <shai@scalex86.org>
Signed-off-by : Ravikiran Thirumalai <kiran@scalex86.org>

Index: alloc_percpu-2.6.13/drivers/net/loopback.c
===================================================================
--- alloc_percpu-2.6.13.orig/drivers/net/loopback.c	2005-08-28 16:41:01.000000000 -0700
+++ alloc_percpu-2.6.13/drivers/net/loopback.c	2005-09-12 12:04:25.000000000 -0700
@@ -226,6 +226,12 @@
 		loopback_dev.priv = stats;
 		loopback_dev.get_stats = &get_stats;
 	}
+
+	/* 
+	 * This is the only struct net_device not allocated by alloc_netdev
+	 * So explicitly init the bigref hanging off loopback_dev
+	 */
+	bigref_init(&loopback_dev.netdev_refcnt);
 	
 	return register_netdev(&loopback_dev);
 };
Index: alloc_percpu-2.6.13/include/linux/netdevice.h
===================================================================
--- alloc_percpu-2.6.13.orig/include/linux/netdevice.h	2005-08-28 16:41:01.000000000 -0700
+++ alloc_percpu-2.6.13/include/linux/netdevice.h	2005-09-12 11:54:21.000000000 -0700
@@ -37,6 +37,7 @@
 #include <linux/config.h>
 #include <linux/device.h>
 #include <linux/percpu.h>
+#include <linux/bigref.h>
 
 struct divert_blk;
 struct vlan_group;
@@ -377,7 +378,7 @@
 	/* device queue lock */
 	spinlock_t		queue_lock;
 	/* Number of references to this device */
-	atomic_t		refcnt;
+	struct bigref	        netdev_refcnt;	
 	/* delayed register/unregister */
 	struct list_head	todo_list;
 	/* device name hash chain */
@@ -677,11 +678,11 @@
 
 static inline void dev_put(struct net_device *dev)
 {
-	atomic_dec(&dev->refcnt);
+	bigref_put(&dev->netdev_refcnt, NULL);
 }
 
-#define __dev_put(dev) atomic_dec(&(dev)->refcnt)
-#define dev_hold(dev) atomic_inc(&(dev)->refcnt)
+#define __dev_put(dev) bigref_put(&(dev)->netdev_refcnt, NULL);
+#define dev_hold(dev) bigref_get(&(dev)->netdev_refcnt);
 
 /* Carrier loss detection, dial on demand. The functions netif_carrier_on
  * and _off may be called from IRQ context, but it is caller
Index: alloc_percpu-2.6.13/net/core/dev.c
===================================================================
--- alloc_percpu-2.6.13.orig/net/core/dev.c	2005-08-28 16:41:01.000000000 -0700
+++ alloc_percpu-2.6.13/net/core/dev.c	2005-09-12 11:54:21.000000000 -0700
@@ -2658,6 +2658,7 @@
 		goto out;
 
 	dev->iflink = -1;
+	bigref_set(&dev->netdev_refcnt, 0);
 
 	/* Init, if this function is available */
 	if (dev->init) {
@@ -2808,7 +2809,7 @@
 	unsigned long rebroadcast_time, warning_time;
 
 	rebroadcast_time = warning_time = jiffies;
-	while (atomic_read(&dev->refcnt) != 0) {
+	while ( bigref_val(&dev->netdev_refcnt) != 0) {
 		if (time_after(jiffies, rebroadcast_time + 1 * HZ)) {
 			rtnl_shlock();
 
@@ -2838,7 +2839,7 @@
 			printk(KERN_EMERG "unregister_netdevice: "
 			       "waiting for %s to become free. Usage "
 			       "count = %d\n",
-			       dev->name, atomic_read(&dev->refcnt));
+			       dev->name, bigref_val(&dev->netdev_refcnt));
 			warning_time = jiffies;
 		}
 	}
@@ -2909,7 +2910,7 @@
 			netdev_wait_allrefs(dev);
 
 			/* paranoia */
-			BUG_ON(atomic_read(&dev->refcnt));
+			BUG_ON(bigref_val(&dev->netdev_refcnt));
 			BUG_TRAP(!dev->ip_ptr);
 			BUG_TRAP(!dev->ip6_ptr);
 			BUG_TRAP(!dev->dn_ptr);
@@ -2969,6 +2970,7 @@
 
 	setup(dev);
 	strcpy(dev->name, name);
+	bigref_init(&dev->netdev_refcnt);
 	return dev;
 }
 EXPORT_SYMBOL(alloc_netdev);
@@ -2986,6 +2988,7 @@
 #ifdef CONFIG_SYSFS
 	/*  Compatiablity with error handling in drivers */
 	if (dev->reg_state == NETREG_UNINITIALIZED) {
+		bigref_destroy(&dev->netdev_refcnt);
 		kfree((char *)dev - dev->padded);
 		return;
 	}
@@ -2996,6 +2999,7 @@
 	/* will free via class release */
 	class_device_put(&dev->class_dev);
 #else
+	bigref_destroy(&dev->netdev_refcnt);
 	kfree((char *)dev - dev->padded);
 #endif
 }
@@ -3210,7 +3214,7 @@
 		set_bit(__LINK_STATE_START, &queue->backlog_dev.state);
 		queue->backlog_dev.weight = weight_p;
 		queue->backlog_dev.poll = process_backlog;
-		atomic_set(&queue->backlog_dev.refcnt, 1);
+		bigref_init(&queue->backlog_dev.netdev_refcnt);
 	}
 
 	dev_boot_phase = 0;
Index: alloc_percpu-2.6.13/net/core/net-sysfs.c
===================================================================
--- alloc_percpu-2.6.13.orig/net/core/net-sysfs.c	2005-08-28 16:41:01.000000000 -0700
+++ alloc_percpu-2.6.13/net/core/net-sysfs.c	2005-09-12 11:54:21.000000000 -0700
@@ -16,6 +16,7 @@
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
 #include <linux/wireless.h>
+#include <linux/bigref.h>
 
 #define to_class_dev(obj) container_of(obj,struct class_device,kobj)
 #define to_net_dev(class) container_of(class, struct net_device, class_dev)
@@ -400,6 +401,8 @@
 		= container_of(cd, struct net_device, class_dev);
 
 	BUG_ON(dev->reg_state != NETREG_RELEASED);
+	
+	bigref_destroy(&dev->netdev_refcnt);
 
 	kfree((char *)dev - dev->padded);
 }

^ permalink raw reply

* TCP oopsing continues
From: Jeff Garzik @ 2005-09-13 14:43 UTC (permalink / raw)
  To: netdev; +Cc: Thomas Graf, Herbert Xu, David S. Miller, Dave Jones,
	Linux Kernel
In-Reply-To: <20050910203131.GB22129@postel.suug.ch>

Well, my oops continues in 2.6.14-rc1.  x86 SMP firewall box.

I still haven't found my null modem cable, so I don't have the top of 
the trace.  Here is everything that was on the screen:

ip_local_deliver_finish
tcp_v4_do_rcv
tcp_v4_rcv
ip_local_deliver
ip_local_deliver_finish
ip_rcv
ip_rcv_finish
netif_receive_skb
e1000_clean_rx_irq
rtl8139_isr_ack
e1000_clean
net_rx_action
__do_softirq
do_softirq
do_IRQ

^ permalink raw reply

* is it safe to use skb_linearize() within a network driver
From: Nicolas DET @ 2005-09-13 14:42 UTC (permalink / raw)
  To: netdev; +Cc: Christoph Hellwig, Sven Luther, Dale Farnsworth

Hello,

First, you can find here 
old;
http://arrakin.homedns.org/~nicolas/mv643xx_eth.tar.gz
http://arrakin.homedns.org/~nicolas/mv643xx_eth.diff.bz2

more up to date:
http://arrakin.homedns.org/~nicolas/mv643xx_eth_small.tar.gz
a small patch for the mv643xx_eth driver.

But his is not my concern ATM. I recently noticed I got:

Badness in local_bh_enable at kernel/softirq.c:140
Call trace:
 [c0005758] check_bug_trap+0x98/0xdc
 [c0005904] ProgramCheckException+0x168/0x4c0
 [c0004ee4] ret_from_except_full+0x0/0x4c
 [c0021424] local_bh_enable+0x18/0x88
 [c025c928] skb_copy_bits+0x144/0x37c
 [c0263b64] __skb_linearize+0x90/0x158
 [e106ac68] mv643xx_eth_start_xmit+0x54c/0x610 [mv643xx_eth]
 [c0263df0] dev_queue_xmit+0x1c4/0x35c
 [c028e414] ip_finish_output+0x130/0x2b8
 [c028e85c] ip_queue_xmit+0x2c0/0x540
 [c029e920] tcp_transmit_skb+0x344/0x7c4
 [c029fc4c] __tcp_push_pending_frames+0x228/0x4a0
 [c029ce90] tcp_rcv_established+0x414/0x8b4
 [c02a65bc] tcp_v4_do_rcv+0x16c/0x35c
 [c02a713c] tcp_v4_rcv+0x990/0xac8

when stressing the mv643xx_eth driver.

The driver does on xmit:
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
            skb_frag_t *fragp;

            fragp = &skb_shinfo(skb)->frags[frag];
            if (fragp->size <= 8 && fragp->page_offset & 0x7) {
                skb_linearize(skb, GFP_ATOMIC);
                printk(KERN_DEBUG "%s: unaligned tiny fragment"
                        "%d of %d, fixed\n",
                        dev->name, frag,
                        skb_shinfo(skb)->nr_frags);
                goto linear;
            }
        }

This routine checks if the hw is capable to send every fragments of a
scatter skb. If not, it calls skb_linearize() and send the packet as it
would do for linear skb.

However, this code is executed into a spin_lock_irq() and:
* skb_linearize() (net/dev/core.c) calls skb_copy_bits()
(net/core/skbuff.c)
* skb_copy_bits() may call  kunmap_skb_frag() (include/linux/skbuff.h)
* kunmap_skb_frag() will call local_bh_enable() (kernel/softirq.c)

and the first line of   local_bh_enable() is 'WARN_ON(irqs_disabled());'

I guess spin_lock_irq() disable the IRQ, and then local_bh_enable() isn't
so happy about this.

Maybe it's a trivial issue (?).
I just wanted to reported this issue I have.

Your sincerly,
-- 
Nicolas DET
MorphOS & Linux developer

^ permalink raw reply

* Re: pm_register should die
From: Pavel Machek @ 2005-09-13 12:12 UTC (permalink / raw)
  To: David McCullough
  Cc: kernel list, Andrew Morton, Linus Torvalds, vojtech, dwmw2,
	netdev, benjamin_kong, dagb, jgarzik, twoller, alan, mm, scott,
	jsimmons
In-Reply-To: <20050913000335.GA10418@beast>

Hi!

> > pm_register has been obsoleted by driver model, and it was deprecated
> > quite long time ago. There are only 13 users left.
> > 
> > Attached is a patch that makes pm_register config-option, so that we
> > don't get the warnings on sane systems. Pretty please, remove usage of
> > pm_register from your subsystem.
> > 
> > IRDA has no usefull MAINTAINER entry; it would be nice if that could
> > be fixed. Alan is best contact I could find for ad1848... does someone
> > care about that driver, anyway? nm256_audio is written by
> > anonymous. Wonderfull...
> > 
> > Okay, it seems to me only users that matter are mtdcore, 3c509 and
> > maybe h3600_ts_input. After those are fixed, it should be okay to just
> > config it out/remove pm_register completely.
> 
> Feel free to clean out pm_register usage in:
> 
> 	drivers/serial/68328serial.c
> 
> there's not much in there that cannot be added later if actually required,

I'd rather have someone who actually has that hardware to convert it
to driver model and test properly.
								Pavel
-- 
if you have sharp zaurus hardware you don't need... you know my address

^ permalink raw reply

* Re: 2.613: network write socket problems
From: Bernd Schubert @ 2005-09-13  9:22 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel
In-Reply-To: <200509121739.46172.bernd.schubert@pci.uni-heidelberg.de>

On Monday 12 September 2005 17:39, Bernd Schubert wrote:
> Hello,
>
> on last Friday  we switched on our server to 2.6.13 and today we are
> experiencing problems with our nfs clients.
> In particular I'm talking about the unfs3 daemon, not the kernel nfs
> daemon. Both are running on the server but on different ports, of course. 
> Both are also serving to the same clients, but different directories.
>
> Today it already several times happend that the unfs3 daemon stalled.
> Ethereal showed no network packages on the unfs3 daemon port during this
> time. A strace to the proc-id of the daemon clearly shows that *some*
> writes to some network sockets will take ages to finish
>
> write(37, "\200\0\0x\203\326(\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 124)
> = 124

Sorry for the noise, its not a kernel problem. Switching back to 2.6.11 didn't 
help, so we investigated further. It turned out, that one of our clients was 
in a kind of a zombie state and asking for filehandles, but not answering 
request from the server. Since unfs3 is only single threaded, all other 
clients had to wait for timeouts.

Bernd

^ permalink raw reply

* Re: pm_register should die
From: Alan Cox @ 2005-09-13  1:32 UTC (permalink / raw)
  To: David McCullough
  Cc: Pavel Machek, kernel list, Andrew Morton, Linus Torvalds, vojtech,
	dwmw2, netdev, benjamin_kong, dagb, jgarzik, twoller, alan, mm,
	scott, jsimmons
In-Reply-To: <20050913000335.GA10418@beast>

> > be fixed. Alan is best contact I could find for ad1848... does someone
> > care about that driver, anyway? nm256_audio is written by
> > anonymous. Wonderfull...

AD1848 docs are public, NM256 was reverse engineered so no docs. Most
users are now using the ALSA layer. It might be simplest to kill
pm_register after OSS goes, which is now scheduled anyway.

^ permalink raw reply

* Re: pm_register should die
From: David McCullough @ 2005-09-13  0:03 UTC (permalink / raw)
  To: Pavel Machek
  Cc: kernel list, Andrew Morton, Linus Torvalds, vojtech, dwmw2,
	netdev, benjamin_kong, dagb, jgarzik, twoller, alan, mm, scott,
	jsimmons
In-Reply-To: <20050912093456.GA29205@elf.ucw.cz>


Jivin Pavel Machek lays it down ...
> Hi!
> 
> pm_register has been obsoleted by driver model, and it was deprecated
> quite long time ago. There are only 13 users left.
> 
> Attached is a patch that makes pm_register config-option, so that we
> don't get the warnings on sane systems. Pretty please, remove usage of
> pm_register from your subsystem.
> 
> IRDA has no usefull MAINTAINER entry; it would be nice if that could
> be fixed. Alan is best contact I could find for ad1848... does someone
> care about that driver, anyway? nm256_audio is written by
> anonymous. Wonderfull...
> 
> Okay, it seems to me only users that matter are mtdcore, 3c509 and
> maybe h3600_ts_input. After those are fixed, it should be okay to just
> config it out/remove pm_register completely.

Feel free to clean out pm_register usage in:

	drivers/serial/68328serial.c

there's not much in there that cannot be added later if actually required,

Cheers,
Davidm

-- 
David McCullough, davidm@cyberguard.com.au, Custom Embedded Solutions + Security
Ph:+61 734352815 Fx:+61 738913630 http://www.uCdot.org http://www.cyberguard.com

^ permalink raw reply

* Re: [PATCH] af_packet: Allow for > 8 byte hardware addresses.
From: David S. Miller @ 2005-09-12 22:45 UTC (permalink / raw)
  To: ebiederm; +Cc: openib-general, netdev
In-Reply-To: <m1ek7ulyt8.fsf@ebiederm.dsl.xmission.com>

From: ebiederm@xmission.com (Eric W. Biederman)
Date: Mon, 12 Sep 2005 16:13:23 -0600

> Updated patch will follow in a bit.

Thanks for following up on this Eric.

^ permalink raw reply

* Re: [PATCH] af_packet: Allow for > 8 byte hardware addresses.
From: Eric W. Biederman @ 2005-09-12 22:13 UTC (permalink / raw)
  To: David S. Miller; +Cc: openib-general, netdev
In-Reply-To: <20050912.141351.50320521.davem@davemloft.net>

"David S. Miller" <davem@davemloft.net> writes:

> From: ebiederm@xmission.com (Eric W. Biederman)
> Date: Sat, 10 Sep 2005 11:25:27 -0600
>
>> @@ -1315,11 +1340,16 @@ packet_setsockopt(struct socket *sock, i
>>  	case PACKET_ADD_MEMBERSHIP:	
>>  	case PACKET_DROP_MEMBERSHIP:
>>  	{
>> -		struct packet_mreq mreq;
>> -		if (optlen<sizeof(mreq))
>> +		struct packet_mreq_max mreq;
>> +		int len = optlen;
>> +		if (len < sizeof(struct packet_mreq))
>>  			return -EINVAL;
>> -		if (copy_from_user(&mreq,optval,sizeof(mreq)))
>> +		if (len > sizeof(mreq))
>> +			len = sizeof(mreq);
>> +		if (copy_from_user(&mreq,optval,len))
>>  			return -EFAULT;
>
> I would suggest memset()'ing out any packet_mreq_max structure,
> before copying a smaller amount of data into it, just to be
> safe.  Please check this out in all such possible uses in
> the patch.
>
> Thanks.

Ok.  For that specific case you have quoted the only instance.

In a practical sense it doesn't matter because halen determines
how many of the bytes we actually look at.  But if something
is buggy I can see the memset causing the bug to act in a
more deterministic fashion.

Updated patch will follow in a bit.

Eric

^ permalink raw reply

* Re: Hamradio driver cleanups
From: David S. Miller @ 2005-09-12 21:18 UTC (permalink / raw)
  To: ralf; +Cc: jgarzik, linux-hams, netdev
In-Reply-To: <20050911212913.GA8786@linux-mips.org>


Jeff, I'll take care of merging all of Ralf's changes.
Thanks.

^ permalink raw reply

* Re: [PATCH] af_packet: Allow for > 8 byte hardware addresses.
From: David S. Miller @ 2005-09-12 21:13 UTC (permalink / raw)
  To: ebiederm; +Cc: openib-general, netdev
In-Reply-To: <m164t8ltrs.fsf_-_@ebiederm.dsl.xmission.com>

From: ebiederm@xmission.com (Eric W. Biederman)
Date: Sat, 10 Sep 2005 11:25:27 -0600

> @@ -1315,11 +1340,16 @@ packet_setsockopt(struct socket *sock, i
>  	case PACKET_ADD_MEMBERSHIP:	
>  	case PACKET_DROP_MEMBERSHIP:
>  	{
> -		struct packet_mreq mreq;
> -		if (optlen<sizeof(mreq))
> +		struct packet_mreq_max mreq;
> +		int len = optlen;
> +		if (len < sizeof(struct packet_mreq))
>  			return -EINVAL;
> -		if (copy_from_user(&mreq,optval,sizeof(mreq)))
> +		if (len > sizeof(mreq))
> +			len = sizeof(mreq);
> +		if (copy_from_user(&mreq,optval,len))
>  			return -EFAULT;

I would suggest memset()'ing out any packet_mreq_max structure,
before copying a smaller amount of data into it, just to be
safe.  Please check this out in all such possible uses in
the patch.

Thanks.

^ permalink raw reply

* Re: [patch 2.6.13 0/5] normalize calculations of rx_dropped
From: John W. Linville @ 2005-09-12 19:14 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: linux-kernel, netdev, akpm, john.ronciak, ganesh.venkatesan,
	cramerj, jesse.brandeburg, ayyappan.veeraiyan, mchan, davem
In-Reply-To: <4325CEAB.2050600@pobox.com>

On Mon, Sep 12, 2005 at 02:53:31PM -0400, Jeff Garzik wrote:

> For e.g. e1000, are we sure that packets dropped by hardware are 
> accounted elsewhere?

The e100 and tg3 patches move the count of those frames to
rx_missed_errors.  e1000 and ixgb were already counting them there in
addition to rx_discards, so they were simply removed from rx_discards.
3c59x was counting other errors in rx_discards, so they were removed
from that count.

John
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply

* RE: Git broken for IPW2200
From: Alejandro Bonilla @ 2005-09-12 19:08 UTC (permalink / raw)
  To: 'Jeff Garzik'
  Cc: netdev, 'Linus Torvalds', ieee80211-devel,
	'linux-kernel'
In-Reply-To: <4325CEFA.6050307@pobox.com>

> Alejandro Bonilla Beeche wrote:
> > Hi,
> > 
> > 	Where does one report this? I was building Linus Git 
> tree as per I
> > updated it at 09/07/2005 7:00PM PDT and got this while compiling.
> > 
> > Where do I report this?
> > 
> > Debian unstable updated at same time.
> > 
> > it looks like ipw2200 is thinking that ieee80211 is not 
> compiled in, but
> > I did select it as a module?
> 
> Care to send your .config?
> 
> 	Jeff

Jeff,

	http://lkml.org/lkml/2005/9/8/5

It was already fixed anyway, the thread is about 7 days old.

My config is at that URL.

.Alejandro

^ permalink raw reply

* RE: Git broken for IPW2200
From: Alejandro Bonilla @ 2005-09-12 19:04 UTC (permalink / raw)
  To: 'Jeff Garzik', abonilla
  Cc: netdev, 'Linus Torvalds', ieee80211-devel,
	'linux-kernel'
In-Reply-To: <4325CEFA.6050307@pobox.com>


> Alejandro Bonilla Beeche wrote:
> > Hi,
> >
> > 	Where does one report this? I was building Linus Git
> tree as per I
> > updated it at 09/07/2005 7:00PM PDT and got this while compiling.
> >
> > Where do I report this?
> >
> > Debian unstable updated at same time.
> >
> > it looks like ipw2200 is thinking that ieee80211 is not
> compiled in, but
> > I did select it as a module?
>
> Care to send your .config?
>
> 	Jeff

Hi Jeff,

	I already did. Let me see if I can look for the it in some archive, unless
you know how to do this faster. (PC not here ATM)

.Alejandro

^ permalink raw reply

* Re: Git broken for IPW2200
From: Jeff Garzik @ 2005-09-12 18:54 UTC (permalink / raw)
  To: abonilla; +Cc: netdev, Linus Torvalds, ieee80211-devel, linux-kernel
In-Reply-To: <1126143695.5402.11.camel@localhost.localdomain>

Alejandro Bonilla Beeche wrote:
> Hi,
> 
> 	Where does one report this? I was building Linus Git tree as per I
> updated it at 09/07/2005 7:00PM PDT and got this while compiling.
> 
> Where do I report this?
> 
> Debian unstable updated at same time.
> 
> it looks like ipw2200 is thinking that ieee80211 is not compiled in, but
> I did select it as a module?

Care to send your .config?

	Jeff

^ permalink raw reply

* Re: [patch 2.6.13 0/5] normalize calculations of rx_dropped
From: Jeff Garzik @ 2005-09-12 18:53 UTC (permalink / raw)
  To: John W. Linville
  Cc: linux-kernel, netdev, akpm, john.ronciak, ganesh.venkatesan,
	cramerj, jesse.brandeburg, ayyappan.veeraiyan, mchan, davem
In-Reply-To: <09122005104858.332@bilbo.tuxdriver.com>

John W. Linville wrote:
> Some fixes to normalize how rx_dropped is calculated.  This is the
> product of a discussion on netdev on or about 18 August 2005 w/
> the subject '[RFC] stats: how to count "good" packets dropped by
> hardware?'
> 
> Patches for 3c59x, e1000, e100, ixgb, and tg3 to follow.

For e.g. e1000, are we sure that packets dropped by hardware are 
accounted elsewhere?

	Jeff

^ permalink raw reply

* Writing Kernel Module to get Kernel Routing Table Information
From: YongHan Lee @ 2005-09-12 16:51 UTC (permalink / raw)
  To: y_h_lee

Dear Linux-Networking Maintainer,

I am a student of EPFL in Switzerland and do a
semester project in networking.
My subject is "ipv6 multipath AODV routing
implementation".

To achieve my goal I would like to program a kernel
module which allows/enables
multipath routing. This means, if I have several
routes to one destination (but
different next hops) in the kernel routing table, then
I want to choose a route
entry with the desired next hop and not necessary the
first route entry. Since I
do not know well the kernel architecture, especially
the kernel networking
section, I do not know if and how it is possible.

My first idea was to use netfilter for ipv6, but the
multiple routing table with
marks are only implemented for ipv4.
https://lists.netfilter.org/pipermail/netfilter/2005-August/062252.html

And now I try to write a Kernel module which should
retrieve all route entries
from the kernel routing table (fib6_node, rt6_info or
dst_entry struct) by
comparing the destination address, source address and
next hop address with
those of the ip packet. This happens at POST ROUTING
hook. Afterwards, I would
change the destination (struct dst_entry) of the
sk_buff struct of the ip
packet. The problem is not to get the next hop address
of the ip packet.
I have started to write my kernel module, but it was
not able to get the route
entries from the kernel routing table, because a lot
of the functions are
static.
I wanted to iterate the fib6_nodes from the root (like
fib6_lookup(&ip6_routing_table, daddr, saddr) [from
ip6_fib.c]), but the kernel
returns me:
Sep 12 17:31:34 m66533pp kernel: kaodv: Unknown symbol
fib6_lookup
Sep 12 17:31:34 m66533pp kernel: kaodv: Unknown symbol
ip6_routing_table
even they are defined in kallsyms and I included the
ip6_fib.h file.

I would be very glad if you could give me some helps
or advises (how it is
possible or my idea is totally impossible). Some links
to architecture of kernel
routing table would be already a great help for me.

I would like to thank you in advance for your help.

yours faithfully,

Yong-Han Lee





		
__________________________________ 
Yahoo! Mail - PC Magazine Editors' Choice 2005 
http://mail.yahoo.com

^ permalink raw reply

* Re: [PATCH  5/12] Add descriptions to constants
From: Ralf Baechle @ 2005-09-12 16:50 UTC (permalink / raw)
  To: Ingo Oeser; +Cc: David S. Miller, netdev, linux-hams
In-Reply-To: <200509121841.53666.netdev@axxeo.de>

On Mon, Sep 12, 2005 at 06:41:53PM +0200, Ingo Oeser wrote:

> That would not break backward compatibility and now the state machine can be
> self explanatory :-)

The states named by numbers are actually being used in the protocol spec.

  Ralf

^ permalink raw reply

* Re: [PATCH  5/12] Add descriptions to constants
From: Ingo Oeser @ 2005-09-12 16:41 UTC (permalink / raw)
  To: Ralf Baechle DL5RB; +Cc: David S. Miller, netdev, linux-hams
In-Reply-To: <20050911221904.GA9301@linux-mips.org>

Hi Ralf,

Ralf Baechle DL5RB wrote:
> Comment the names used for the AX.25 state machine.

What about making it even more useful by aliasing the enum elements?

> Signed-off-by: Ralf Baechle DL5RB <ralf@linux-mips.org>
>
>  include/net/ax25.h |   10 +++++-----
>  1 files changed, 5 insertions(+), 5 deletions(-)
>
> Index: linux-cvs/include/net/ax25.h
> ===================================================================
> --- linux-cvs.orig/include/net/ax25.h
> +++ linux-cvs/include/net/ax25.h
> @@ -97,11 +97,11 @@
>  /* Define Link State constants. */
>
>  enum {
> -	AX25_STATE_0,
> -	AX25_STATE_1,
> -	AX25_STATE_2,
> -	AX25_STATE_3,
> -	AX25_STATE_4
> +	AX25_STATE_0,			/* Listening */
    +  AX25_STATE_LISTENING = AX25_STATE_0,
> +	AX25_STATE_1,			/* SABM sent */
    +  AX25_STATE_SABM_SENT = AX25_STATE_1,
> +	AX25_STATE_2,			/* DISC sent */
    +  AX25_STATE_DISC_SENT = AX25_STATE_2,
> +	AX25_STATE_3,			/* Established */
    +  AX25_STATE_ESTABLISHED = AX25_STATE_3,
> +	AX25_STATE_4			/* Recovery */
    +  AX25_STATE_RECOVERY = AX25_STATE_4,
>  };

That would not break backward compatibility and now the state machine can be
self explanatory :-)


Regards

Ingo Oeser


^ permalink raw reply

* 2.613: network write socket problems
From: Bernd Schubert @ 2005-09-12 15:39 UTC (permalink / raw)
  To: netdev; +Cc: linux-kernel

Hello,

on last Friday  we switched on our server to 2.6.13 and today we are 
experiencing problems with our nfs clients.
In particular I'm talking about the unfs3 daemon, not the kernel nfs daemon. 
Both are running on the server but on different ports, of course.  Both are 
also serving to the same clients, but different directories.

Today it already several times happend that the unfs3 daemon stalled. Ethereal 
showed no network packages on the unfs3 daemon port during this time. 
A strace to the proc-id of the daemon clearly shows that *some* writes to some 
network sockets will take ages to finish

write(37, "\200\0\0x\203\326(\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 124) = 
124

This kind of writes can take between seconds and minutes, while it usually 
happens much faster than I can count. After the write() to the network 
socket, other operations happen rather fast, until the next write to a 
network socket. (I identified the troublesome filedescriptors by looking 
to /proc/procid/fd).
After restarting the unfs3 daemon everything goes smooth for some time 
(approximately 20min to 2h), until the next write to a filedescriptor stalls.

Any idea whats going on? Until today this never happend before, neither with 
2.6.x nor 2.4.x. As I wrote, on Friday we replaced 2.6.11.12 by 2.6.13, the 
configuration should be similar, only changes should be HZ set to 250 and 
additionally the skge driver. 
We already switched back from skge to sk98lin, but the problem seems to 
remain. 


Thanks,	
	Bernd



-- 
Bernd Schubert
Physikalisch Chemisches Institut / Theoretische Chemie
Universität Heidelberg
INF 229
69120 Heidelberg
e-mail: bernd.schubert@pci.uni-heidelberg.de

^ permalink raw reply

* [patch 2.6.13] e1000: whitespace cleanup in e1000_ethtool_ops
From: John W. Linville @ 2005-09-12 14:49 UTC (permalink / raw)
  To: linux-kernel, netdev; +Cc: jgarzik, john.ronciak, ganesh.venkatesan, cramerj

Fix-up some whitespace inconsistencies in e1000_ethtool_ops.

Signed-off-by: John W. Linville <linville@tuxdriver.com>
---

 drivers/net/e1000/e1000_ethtool.c |   44 +++++++++++++++++++-------------------
 1 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -1705,22 +1705,22 @@ e1000_get_strings(struct net_device *net
 }
 
 struct ethtool_ops e1000_ethtool_ops = {
-	.get_settings           = e1000_get_settings,
-	.set_settings           = e1000_set_settings,
-	.get_drvinfo            = e1000_get_drvinfo,
-	.get_regs_len           = e1000_get_regs_len,
-	.get_regs               = e1000_get_regs,
-	.get_wol                = e1000_get_wol,
-	.set_wol                = e1000_set_wol,
-	.get_msglevel	        = e1000_get_msglevel,
-	.set_msglevel	        = e1000_set_msglevel,
-	.nway_reset             = e1000_nway_reset,
-	.get_link               = ethtool_op_get_link,
-	.get_eeprom_len         = e1000_get_eeprom_len,
-	.get_eeprom             = e1000_get_eeprom,
-	.set_eeprom             = e1000_set_eeprom,
-	.get_ringparam          = e1000_get_ringparam,
-	.set_ringparam          = e1000_set_ringparam,
+	.get_settings		= e1000_get_settings,
+	.set_settings		= e1000_set_settings,
+	.get_drvinfo		= e1000_get_drvinfo,
+	.get_regs_len		= e1000_get_regs_len,
+	.get_regs		= e1000_get_regs,
+	.get_wol		= e1000_get_wol,
+	.set_wol		= e1000_set_wol,
+	.get_msglevel		= e1000_get_msglevel,
+	.set_msglevel		= e1000_set_msglevel,
+	.nway_reset		= e1000_nway_reset,
+	.get_link		= ethtool_op_get_link,
+	.get_eeprom_len		= e1000_get_eeprom_len,
+	.get_eeprom		= e1000_get_eeprom,
+	.set_eeprom		= e1000_set_eeprom,
+	.get_ringparam		= e1000_get_ringparam,
+	.set_ringparam		= e1000_set_ringparam,
 	.get_pauseparam		= e1000_get_pauseparam,
 	.set_pauseparam		= e1000_set_pauseparam,
 	.get_rx_csum		= e1000_get_rx_csum,
@@ -1733,12 +1733,12 @@ struct ethtool_ops e1000_ethtool_ops = {
 	.get_tso		= ethtool_op_get_tso,
 	.set_tso		= e1000_set_tso,
 #endif
-	.self_test_count        = e1000_diag_test_count,
-	.self_test              = e1000_diag_test,
-	.get_strings            = e1000_get_strings,
-	.phys_id                = e1000_phys_id,
-	.get_stats_count        = e1000_get_stats_count,
-	.get_ethtool_stats      = e1000_get_ethtool_stats,
+	.self_test_count	= e1000_diag_test_count,
+	.self_test		= e1000_diag_test,
+	.get_strings		= e1000_get_strings,
+	.phys_id		= e1000_phys_id,
+	.get_stats_count	= e1000_get_stats_count,
+	.get_ethtool_stats	= e1000_get_ethtool_stats,
 	.get_perm_addr		= ethtool_op_get_perm_addr,
 };
 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox