Netdev List
 help / color / mirror / Atom feed
* Re: [possibly OT] for_each_netdev() in 2.6.23-gitX / 2.6.24-rc1-gitY breaks Cisco VPN client
From: Stephen Hemminger @ 2007-10-31  5:05 UTC (permalink / raw)
  To: Alessandro Suardi; +Cc: linux-kernel, netdev
In-Reply-To: <5a4c581d0710301735h1682a30bvfbee632c118556d8@mail.gmail.com>

On Wed, 31 Oct 2007 01:35:47 +0100
"Alessandro Suardi" <alessandro.suardi@gmail.com> wrote:

> It's been a while I noticed, but I thought someone would as usual
>  cook up some fix, while I don't even see the issue been reported...
>  if this isn't a Linux kernel/net issue just drop my email, thanks.
> 
> Error message during cisco_vpn.ko build:
> 
> /download/linux/net/vpnclient/interceptor.c:345:23: error: macro
> "for_each_netdev" requires 2 arguments, but only 1 given
> 

RTFM Documentation/stable_api_nonsense.txt


-- 
Stephen Hemminger <shemminger@linux-foundation.org>

^ permalink raw reply

* Re: [PATCH 09/33] mm: system wide ALLOC_NO_WATERMARK
From: Nick Piggin @ 2007-10-31  3:52 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Linus Torvalds, Andrew Morton, linux-kernel, linux-mm, netdev,
	trond.myklebust
In-Reply-To: <20071030160912.283002000@chello.nl>

On Wednesday 31 October 2007 03:04, Peter Zijlstra wrote:
> Change ALLOC_NO_WATERMARK page allocation such that the reserves are system
> wide - which they are per setup_per_zone_pages_min(), when we scrape the
> barrel, do it properly.
>

IIRC it's actually not too uncommon to have allocations coming here via
page reclaim. It's not exactly clear that you want to break mempolicies
at this point.


> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> ---
>  mm/page_alloc.c |    6 ++++++
>  1 file changed, 6 insertions(+)
>
> Index: linux-2.6/mm/page_alloc.c
> ===================================================================
> --- linux-2.6.orig/mm/page_alloc.c
> +++ linux-2.6/mm/page_alloc.c
> @@ -1638,6 +1638,12 @@ restart:
>  rebalance:
>  	if (alloc_flags & ALLOC_NO_WATERMARKS) {
>  nofail_alloc:
> +		/*
> +		 * break out of mempolicy boundaries
> +		 */
> +		zonelist = NODE_DATA(numa_node_id())->node_zonelists +
> +			gfp_zone(gfp_mask);
> +
>  		/* go through the zonelist yet again, ignoring mins */
>  		page = get_page_from_freelist(gfp_mask, order, zonelist,
>  				ALLOC_NO_WATERMARKS);
>
> --
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 06/33] mm: allow PF_MEMALLOC from softirq context
From: Nick Piggin @ 2007-10-31  3:51 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Linus Torvalds, Andrew Morton, linux-kernel, linux-mm, netdev,
	trond.myklebust
In-Reply-To: <20071030160911.540148000@chello.nl>

On Wednesday 31 October 2007 03:04, Peter Zijlstra wrote:
> Allow PF_MEMALLOC to be set in softirq context. When running softirqs from
> a borrowed context save current->flags, ksoftirqd will have its own
> task_struct.


What's this for? Why would ksoftirqd pick up PF_MEMALLOC? (I guess
that some networking thing must be picking it up in a subsequent patch,
but I'm too lazy to look!)... Again, can you have more of a rationale in
your patch headers, or ref the patch that uses it... thanks


^ permalink raw reply

* Re: [patch 1/1][CORE] resend - fix free_netdev on register_netdev failure
From: Stephen Hemminger @ 2007-10-31  4:52 UTC (permalink / raw)
  To: David Miller; +Cc: dlezcano, netdev
In-Reply-To: <20071030.153830.120597346.davem@davemloft.net>

On Tue, 30 Oct 2007 15:38:30 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:

> From: Daniel Lezcano <dlezcano@fr.ibm.com>
> Date: Tue, 30 Oct 2007 17:19:26 +0100
> 
> > Point 1:
> > The unregistering of a network device schedule a netdev_run_todo.
> > This function calls dev->destructor when it is set and the
> > destructor calls free_netdev.
> > 
> > Point 2:
> > In the case of an initialization of a network device the usual code
> > is:
> >  * alloc_netdev
> >  * register_netdev
> >     -> if this one fails, call free_netdev and exit with error.
> > 
> > Point 3:
> > In the register_netdevice function at the later state, when the device
> > is at the registered state, a call to the netdevice_notifiers is made.
> > If one of the notification falls into an error, a rollback to the
> > registered state is done using unregister_netdevice.
> > 
> > Conclusion:
> > When a network device fails to register during initialization because
> > one network subsystem returned an error during a notification call
> > chain, the network device is freed twice because of fact 1 and fact 2.
> > The second free_netdev will be done with an invalid pointer.
> > 
> > Proposed solution:
> > The following patch move all the code of unregister_netdevice *except* 
> > the call to net_set_todo, to a new function "rollback_registered".
> > 
> > The following functions are changed in this way:
> >  * register_netdevice: calls rollback_registered when a notification fails
> >  * unregister_netdevice: calls rollback_register + net_set_todo, the call
> >                          order to net_set_todo is changed because it is the
> >                          latest now. Since it justs add an element to a list
> >                          that should not break anything.
> > 
> > Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
> 
> Looks good, applied.

Agreed, but I wish the unwind code wouldn't have to be separate function.

-- 
Stephen Hemminger <shemminger@linux-foundation.org>

^ permalink raw reply

* Re: [PATCH 05/33] mm: kmem_estimate_pages()
From: Nick Piggin @ 2007-10-31  3:43 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Linus Torvalds, Andrew Morton, linux-kernel, linux-mm, netdev,
	trond.myklebust
In-Reply-To: <20071030160911.281698000@chello.nl>

On Wednesday 31 October 2007 03:04, Peter Zijlstra wrote:
> Provide a method to get the upper bound on the pages needed to allocate
> a given number of objects from a given kmem_cache.
>

Fair enough, but just to make it a bit easier, can you provide a
little reason of why in this patch (or reference the patch number
where you use it, or put it together with the patch where you use
it, etc.).

Thanks,

^ permalink raw reply

* Re: [PATCH 03/33] mm: slub: add knowledge of reserve pages
From: Nick Piggin @ 2007-10-31  3:37 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Linus Torvalds, Andrew Morton, linux-kernel, linux-mm, netdev,
	trond.myklebust
In-Reply-To: <20071030160910.813944000@chello.nl>

On Wednesday 31 October 2007 03:04, Peter Zijlstra wrote:
> Restrict objects from reserve slabs (ALLOC_NO_WATERMARKS) to allocation
> contexts that are entitled to it.
>
> Care is taken to only touch the SLUB slow path.
>
> This is done to ensure reserve pages don't leak out and get consumed.

I think this is generally a good idea (to prevent slab allocators
from stealing reserve). However I naively think the implementation
is a bit overengineered and thus has a few holes.

Humour me, what was the problem with failing the slab allocation
(actually, not fail but just call into the page allocator to do
correct waiting  / reclaim) in the slowpath if the process fails the
watermark checks?

^ permalink raw reply

* Re: [PATCH] af_key: suppress a warning for 64k pages.
From: David Miller @ 2007-10-31  4:42 UTC (permalink / raw)
  To: sfr; +Cc: netdev, linux-kernel
In-Reply-To: <20071031153422.44f864e8.sfr@canb.auug.org.au>

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Wed, 31 Oct 2007 15:34:22 +1100

> On Tue, 30 Oct 2007 21:08:46 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
> > I think we should retain the check, but modify it so that GCC knows we
> > understand that it's OK if it is always false.  Perhaps a simple (u32)
> > cast on the left branch of the comparison is sufficient?
> 
> Unfortunately, that does not suppress the warning (gcc is getting too
> smart :-().

It seems if you break the comparison out into a function which
takes a u32, that's enough to get rid of the warning.

I can't figure out a way to make this prettier, can you?

#define PAGE_SIZE	(64 * 1024)

typedef unsigned int u32;
typedef unsigned short u16;

int compare(u32 val)
{
	if (val >= PAGE_SIZE)
		return -1;
	return 0;
}

int foo(u16 val)
{
#if 1
	return compare(val);
#else
	if (val >= PAGE_SIZE)
		return -1;
	return 0;
#endif
}

^ permalink raw reply

* Re: [PATCH 00/33] Swap over NFS -v14
From: David Miller @ 2007-10-31  4:37 UTC (permalink / raw)
  To: nickpiggin
  Cc: a.p.zijlstra, torvalds, akpm, linux-kernel, linux-mm, netdev,
	trond.myklebust
In-Reply-To: <200710311426.33223.nickpiggin@yahoo.com.au>

From: Nick Piggin <nickpiggin@yahoo.com.au>
Date: Wed, 31 Oct 2007 14:26:32 +1100

> Is it really worth all the added complexity of making swap
> over NFS files work, given that you could use a network block
> device instead?

Don't be misled.  Swapping over NFS is just a scarecrow for the
seemingly real impetus behind these changes which is network storage
stuff like iSCSI.

^ permalink raw reply

* Re: [PATCH] af_key: suppress a warning for 64k pages.
From: Stephen Rothwell @ 2007-10-31  4:34 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-kernel
In-Reply-To: <20071030.210846.215166155.davem@davemloft.net>

[-- Attachment #1: Type: text/plain, Size: 622 bytes --]

On Tue, 30 Oct 2007 21:08:46 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
>
> I'm not so sure ifdef'ing things up all over the place is the way to
> solve this.  It makes the code ultra ugly.

I agree.

> I think we should retain the check, but modify it so that GCC knows we
> understand that it's OK if it is always false.  Perhaps a simple (u32)
> cast on the left branch of the comparison is sufficient?

Unfortunately, that does not suppress the warning (gcc is getting too
smart :-().

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH 00/33] Swap over NFS -v14
From: Nick Piggin @ 2007-10-31  3:26 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Linus Torvalds, Andrew Morton, linux-kernel, linux-mm, netdev,
	trond.myklebust
In-Reply-To: <20071030160401.296770000@chello.nl>

On Wednesday 31 October 2007 03:04, Peter Zijlstra wrote:
> Hi,
>
> Another posting of the full swap over NFS series.

Hi,

Is it really worth all the added complexity of making swap
over NFS files work, given that you could use a network block
device instead?

Also, have you ensured that page_file_index, page_file_mapping
and page_offset are only ever used on anonymous pages when the
page is locked? (otherwise PageSwapCache could change)

^ permalink raw reply

* Re: [PATCH] af_key: suppress a warning for 64k pages.
From: David Miller @ 2007-10-31  4:08 UTC (permalink / raw)
  To: sfr; +Cc: netdev, linux-kernel
In-Reply-To: <20071031145954.fe106f73.sfr@canb.auug.org.au>

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Wed, 31 Oct 2007 14:59:54 +1100

> On PowerPC allmodconfig build we get this:
> 
> net/key/af_key.c:400: warning: comparison is always false due to limited range of data type
> 
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
...
>  
> +	/* sadb_x_ctx_len is uint16_t */
> +#if PAGE_SIZE < (1 << 16)
>  	if (sec_ctx->sadb_x_ctx_len > PAGE_SIZE)
>  		return -EINVAL;
> +#endif
>  
>  	len = pfkey_sec_ctx_len(sec_ctx);
>  

I'm not so sure ifdef'ing things up all over the place is the way to
solve this.  It makes the code ultra ugly.

I think we should retain the check, but modify it so that GCC knows we
understand that it's OK if it is always false.  Perhaps a simple (u32)
cast on the left branch of the comparison is sufficient?

^ permalink raw reply

* Re: [PATCH 00/33] Swap over NFS -v14
From: Nick Piggin @ 2007-10-31  4:04 UTC (permalink / raw)
  To: David Miller
  Cc: a.p.zijlstra, torvalds, akpm, linux-kernel, linux-mm, netdev,
	trond.myklebust
In-Reply-To: <20071030.213753.126064697.davem@davemloft.net>

On Wednesday 31 October 2007 15:37, David Miller wrote:
> From: Nick Piggin <nickpiggin@yahoo.com.au>
> Date: Wed, 31 Oct 2007 14:26:32 +1100
>
> > Is it really worth all the added complexity of making swap
> > over NFS files work, given that you could use a network block
> > device instead?
>
> Don't be misled.  Swapping over NFS is just a scarecrow for the
> seemingly real impetus behind these changes which is network storage
> stuff like iSCSI.

Oh, I'm OK with the network reserves stuff (not the actual patch,
which I'm not really qualified to review, but at least the idea
of it...).

And also I'm not as such against the idea of swap over network.

However, specifically the change to make swapfiles work through
the filesystem layer (ATM it goes straight to the block layer,
modulo some initialisation stuff which uses block filesystem-
specific calls).

I mean, I assume that anybody trying to swap over network *today*
has to be using a network block device anyway, so the idea of
just being able to transparently improve that case seems better
than adding new complexities for seemingly not much gain.

^ permalink raw reply

* [PATCH] af_key: suppress a warning for 64k pages.
From: Stephen Rothwell @ 2007-10-31  3:59 UTC (permalink / raw)
  To: netdev; +Cc: LKML

On PowerPC allmodconfig build we get this:

net/key/af_key.c:400: warning: comparison is always false due to limited range of data type

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 net/key/af_key.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/net/key/af_key.c b/net/key/af_key.c
index 7969f8a..7da6c1a 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -397,8 +397,11 @@ static inline int verify_sec_ctx_len(void *p)
 	struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p;
 	int len;
 
+	/* sadb_x_ctx_len is uint16_t */
+#if PAGE_SIZE < (1 << 16)
 	if (sec_ctx->sadb_x_ctx_len > PAGE_SIZE)
 		return -EINVAL;
+#endif
 
 	len = pfkey_sec_ctx_len(sec_ctx);
 
-- 
1.5.3.4


^ permalink raw reply related

* [PATCH]: Fix IP1000 config dependencies.
From: David Miller @ 2007-10-31  3:59 UTC (permalink / raw)
  To: jeff; +Cc: netdev


Noticed during some randconfig runs.

[NET]: IP1000 driver needs MII.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 86b8641..895936a 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -168,6 +168,7 @@ config NET_SB1000
 config IP1000
        tristate "IP1000 Gigabit Ethernet support"
        depends on PCI && EXPERIMENTAL
+       select MII
        ---help---
          This driver supports IP1000 gigabit Ethernet cards.
 
-- 
1.5.2.5


^ permalink raw reply related

* Re: dev_ifname32() fails on 32->64bit calls in copy_in_user().
From: David Miller @ 2007-10-31  3:41 UTC (permalink / raw)
  To: benh; +Cc: Joel.Becker, netdev, Linux-Kernel, ebiederm
In-Reply-To: <1193798124.9928.91.camel@pasglop>

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Wed, 31 Oct 2007 13:35:24 +1100

> [PATCH] Fix new dev_ifname32 returning -EFAULT
> 
> A stray semicolon slipped in the patch that updated dev_ifname32 to
> not be inline, causing it to always return -EFAULT. This fixes it.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Applied, thanks for the fix Ben!

^ permalink raw reply

* Re: [PATCH 04/33] mm: allow mempool to fall back to memalloc reserves
From: Nick Piggin @ 2007-10-31  3:40 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Linus Torvalds, Andrew Morton, linux-kernel, linux-mm, netdev,
	trond.myklebust
In-Reply-To: <20071030160911.031845000@chello.nl>

On Wednesday 31 October 2007 03:04, Peter Zijlstra wrote:
> Allow the mempool to use the memalloc reserves when all else fails and
> the allocation context would otherwise allow it.

I don't see what this is for. The whole point of when I fixed this
to *not* use the memalloc reserves is because processes that were
otherwise allowed to use those reserves, were. They should not.



> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> ---
>  mm/mempool.c |   12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> Index: linux-2.6/mm/mempool.c
> ===================================================================
> --- linux-2.6.orig/mm/mempool.c
> +++ linux-2.6/mm/mempool.c
> @@ -14,6 +14,7 @@
>  #include <linux/mempool.h>
>  #include <linux/blkdev.h>
>  #include <linux/writeback.h>
> +#include "internal.h"
>
>  static void add_element(mempool_t *pool, void *element)
>  {
> @@ -204,7 +205,7 @@ void * mempool_alloc(mempool_t *pool, gf
>  	void *element;
>  	unsigned long flags;
>  	wait_queue_t wait;
> -	gfp_t gfp_temp;
> +	gfp_t gfp_temp, gfp_orig = gfp_mask;
>
>  	might_sleep_if(gfp_mask & __GFP_WAIT);
>
> @@ -228,6 +229,15 @@ repeat_alloc:
>  	}
>  	spin_unlock_irqrestore(&pool->lock, flags);
>
> +	/* if we really had right to the emergency reserves try those */
> +	if (gfp_to_alloc_flags(gfp_orig) & ALLOC_NO_WATERMARKS) {
> +		if (gfp_temp & __GFP_NOMEMALLOC) {
> +			gfp_temp &= ~(__GFP_NOMEMALLOC|__GFP_NOWARN);
> +			goto repeat_alloc;
> +		} else
> +			gfp_temp |= __GFP_NOMEMALLOC|__GFP_NOWARN;
> +	}
> +
>  	/* We must not sleep in the GFP_ATOMIC case */
>  	if (!(gfp_mask & __GFP_WAIT))
>  		return NULL;
>
> --

^ permalink raw reply

* [PATCH]: Fix networking scatterlist regressions.
From: David Miller @ 2007-10-31  3:40 UTC (permalink / raw)
  To: netdev; +Cc: herbert, rusty, jens.axboe


I just checked the following bug fix into net-2.6

Rusty, have a quick look at virtio_net wrt. the changes I
made to skb_to_sgvec()'s behavior.  I think I might have
even fixed something :-)

Jens, please review my commentary wrt. sg_mark_end() and
it's nonintuitive behavior which led to these bugs.

Thanks.

[NET]: Fix incorrect sg_mark_end() calls.

This fixes scatterlist corruptions added by

	commit 68e3f5dd4db62619fdbe520d36c9ebf62e672256
	[CRYPTO] users: Fix up scatterlist conversion errors

The issue is that the code calls sg_mark_end() which clobbers the
sg_page() pointer of the final scatterlist entry.

The first part fo the fix makes skb_to_sgvec() do __sg_mark_end().

After considering all skb_to_sgvec() call sites the most correct
solution is to call __sg_mark_end() in skb_to_sgvec() since that is
what all of the callers would end up doing anyways.

I suspect this might have fixed some problems in virtio_net which is
the sole non-crypto user of skb_to_sgvec().

Other similar sg_mark_end() cases were converted over to
__sg_mark_end() as well.

Arguably sg_mark_end() is a poorly named function because it doesn't
just "mark", it clears out the page pointer as a side effect, which is
what led to these bugs in the first place.

The one remaining plain sg_mark_end() call is in scsi_alloc_sgtable()
and arguably it could be converted to __sg_mark_end() if only so that
we can delete this confusing interface from linux/scatterlist.h

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/core/skbuff.c                     |   16 +++++++++++++---
 net/ipv4/esp4.c                       |   12 +++++++-----
 net/ipv4/tcp_ipv4.c                   |    2 +-
 net/ipv6/esp6.c                       |   13 +++++++------
 net/ipv6/tcp_ipv6.c                   |    2 +-
 net/rxrpc/rxkad.c                     |    9 +++++----
 net/sunrpc/auth_gss/gss_krb5_crypto.c |    6 +++---
 7 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 573e172..64b50ff 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2028,8 +2028,8 @@ void __init skb_init(void)
  *	Fill the specified scatter-gather list with mappings/pointers into a
  *	region of the buffer space attached to a socket buffer.
  */
-int
-skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
+static int
+__skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
 {
 	int start = skb_headlen(skb);
 	int i, copy = start - offset;
@@ -2078,7 +2078,8 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
 			if ((copy = end - offset) > 0) {
 				if (copy > len)
 					copy = len;
-				elt += skb_to_sgvec(list, sg+elt, offset - start, copy);
+				elt += __skb_to_sgvec(list, sg+elt, offset - start,
+						      copy);
 				if ((len -= copy) == 0)
 					return elt;
 				offset += copy;
@@ -2090,6 +2091,15 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
 	return elt;
 }
 
+int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len)
+{
+	int nsg = __skb_to_sgvec(skb, sg, offset, len);
+
+	__sg_mark_end(&sg[nsg - 1]);
+
+	return nsg;
+}
+
 /**
  *	skb_cow_data - Check that a socket buffer's data buffers are writable
  *	@skb: The socket buffer to check.
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index cad4278..c31bccb 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -111,9 +111,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 				goto unlock;
 		}
 		sg_init_table(sg, nfrags);
-		sg_mark_end(sg, skb_to_sgvec(skb, sg, esph->enc_data +
-						      esp->conf.ivlen -
-						      skb->data, clen));
+		skb_to_sgvec(skb, sg,
+			     esph->enc_data +
+			     esp->conf.ivlen -
+			     skb->data, clen);
 		err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
 		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
@@ -205,8 +206,9 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
 			goto out;
 	}
 	sg_init_table(sg, nfrags);
-	sg_mark_end(sg, skb_to_sgvec(skb, sg, sizeof(*esph) + esp->conf.ivlen,
-				     elen));
+	skb_to_sgvec(skb, sg,
+		     sizeof(*esph) + esp->conf.ivlen,
+		     elen);
 	err = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
 	if (unlikely(sg != &esp->sgbuf[0]))
 		kfree(sg);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index d3d8d5d..eec02b2 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1083,7 +1083,7 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
 	sg_set_buf(&sg[block++], key->key, key->keylen);
 	nbytes += key->keylen;
 
-	sg_mark_end(sg, block);
+	__sg_mark_end(&sg[block - 1]);
 
 	/* Now store the Hash into the packet */
 	err = crypto_hash_init(desc);
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index ab17b5e..7db66f1 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -110,9 +110,10 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 				goto unlock;
 		}
 		sg_init_table(sg, nfrags);
-		sg_mark_end(sg, skb_to_sgvec(skb, sg, esph->enc_data +
-						      esp->conf.ivlen -
-						      skb->data, clen));
+		skb_to_sgvec(skb, sg,
+			     esph->enc_data +
+			     esp->conf.ivlen -
+			     skb->data, clen);
 		err = crypto_blkcipher_encrypt(&desc, sg, sg, clen);
 		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
@@ -209,9 +210,9 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
 			}
 		}
 		sg_init_table(sg, nfrags);
-		sg_mark_end(sg, skb_to_sgvec(skb, sg,
-					     sizeof(*esph) + esp->conf.ivlen,
-					     elen));
+		skb_to_sgvec(skb, sg,
+			     sizeof(*esph) + esp->conf.ivlen,
+			     elen);
 		ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
 		if (unlikely(sg != &esp->sgbuf[0]))
 			kfree(sg);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index f1523b8..4b90328 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -781,7 +781,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
 	sg_set_buf(&sg[block++], key->key, key->keylen);
 	nbytes += key->keylen;
 
-	sg_mark_end(sg, block);
+	__sg_mark_end(&sg[block - 1]);
 
 	/* Now store the hash into the packet */
 	err = crypto_hash_init(desc);
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index eebefb6..57458d4 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -237,7 +237,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
 	len = data_size + call->conn->size_align - 1;
 	len &= ~(call->conn->size_align - 1);
 
-	sg_init_table(sg, skb_to_sgvec(skb, sg, 0, len));
+	sg_init_table(sg, nsg);
+	skb_to_sgvec(skb, sg, 0, len);
 	crypto_blkcipher_encrypt_iv(&desc, sg, sg, len);
 
 	_leave(" = 0");
@@ -344,7 +345,7 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call,
 		goto nomem;
 
 	sg_init_table(sg, nsg);
-	sg_mark_end(sg, skb_to_sgvec(skb, sg, 0, 8));
+	skb_to_sgvec(skb, sg, 0, 8);
 
 	/* start the decryption afresh */
 	memset(&iv, 0, sizeof(iv));
@@ -426,7 +427,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
 	}
 
 	sg_init_table(sg, nsg);
-	sg_mark_end(sg, skb_to_sgvec(skb, sg, 0, skb->len));
+	skb_to_sgvec(skb, sg, 0, skb->len);
 
 	/* decrypt from the session key */
 	payload = call->conn->key->payload.data;
@@ -701,7 +702,7 @@ static void rxkad_sg_set_buf2(struct scatterlist sg[2],
 		nsg++;
 	}
 
-	sg_mark_end(sg, nsg);
+	__sg_mark_end(sg, nsg);
 
 	ASSERTCMP(sg[0].length + sg[1].length, ==, buflen);
 }
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
index 91cd8f0..4a8aa94 100644
--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
+++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
@@ -211,8 +211,8 @@ encryptor(struct scatterlist *sg, void *data)
 	if (thislen == 0)
 		return 0;
 
-	sg_mark_end(desc->infrags, desc->fragno);
-	sg_mark_end(desc->outfrags, desc->fragno);
+	__sg_mark_end(desc->infrags, desc->fragno);
+	__sg_mark_end(desc->outfrags, desc->fragno);
 
 	ret = crypto_blkcipher_encrypt_iv(&desc->desc, desc->outfrags,
 					  desc->infrags, thislen);
@@ -293,7 +293,7 @@ decryptor(struct scatterlist *sg, void *data)
 	if (thislen == 0)
 		return 0;
 
-	sg_mark_end(desc->frags, desc->fragno);
+	__sg_mark_end(desc->frags, desc->fragno);
 
 	ret = crypto_blkcipher_decrypt_iv(&desc->desc, desc->frags,
 					  desc->frags, thislen);
-- 
1.5.2.5


^ permalink raw reply related

* Re: dev_ifname32() fails on 32->64bit calls in copy_in_user().
From: Benjamin Herrenschmidt @ 2007-10-31  2:35 UTC (permalink / raw)
  To: Joel Becker
  Cc: Linux Netdev, Linux Kernel Mailing List, Eric W. Biederman,
	David S. Miller
In-Reply-To: <20071031003850.GE7517@tasint.org>

Bug is in the new dev_ifname32:

	uifr = compat_alloc_user_space(sizeof(struct ifreq));
	if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32)));
		return -EFAULT;

There's a stray ";" after the if statement, that was obviously not
tested :-)

This fixes it here (tested):
----------------------------------------------------------------------------
[PATCH] Fix new dev_ifname32 returning -EFAULT

A stray semicolon slipped in the patch that updated dev_ifname32 to
not be inline, causing it to always return -EFAULT. This fixes it.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

Index: linux-work/fs/compat_ioctl.c
===================================================================
--- linux-work.orig/fs/compat_ioctl.c	2007-10-31 13:30:42.000000000 +1100
+++ linux-work/fs/compat_ioctl.c	2007-10-31 13:30:46.000000000 +1100
@@ -322,7 +322,7 @@ static int dev_ifname32(unsigned int fd,
 	int err;
 
 	uifr = compat_alloc_user_space(sizeof(struct ifreq));
-	if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32)));
+	if (copy_in_user(uifr, compat_ptr(arg), sizeof(struct ifreq32)))
 		return -EFAULT;
 
 	err = sys_ioctl(fd, SIOCGIFNAME, (unsigned long)uifr);



^ permalink raw reply

* Re: [PATCH] remove claim balance_rr won't reorder on many to one
From: Rick Jones @ 2007-10-31  1:08 UTC (permalink / raw)
  To: Jay Vosburgh; +Cc: netdev
In-Reply-To: <5242.1193777750@death>

> 	2- next worst is "balance-rr many slow" to "single fast", with
> the reordering rate generally being substantially lower than case #1 (it
> looked like your test showed about a 1% reordering rate, if I'm reading
> your data correctly).

The percentage of reordering for TCP is likely capped by its effect on the 
congestion window, limiting the number of outstanding segments.

rick jones

^ permalink raw reply

* Re: [PATCH] remove claim balance_rr won't reorder on many to one
From: Rick Jones @ 2007-10-31  1:02 UTC (permalink / raw)
  To: Jay Vosburgh; +Cc: netdev
In-Reply-To: <19779.1193790169@death>

Jay Vosburgh wrote:
> Rick Jones <rick.jones2@hp.com> wrote:
> 
> 
>>I have to wonder if the full description of the different versions of
>>being a little bit pregnant is worth it.  Just saying that using
>>balance-rr will result in reordering seems much more simple to comprehend.
> 
> 
> 	True, but the different configurations produce very different
> levels of reordering.
> 
> 	There seem to be users out there trying to use balance-rr to
> maximize single stream TCP throughput (even with reordering), so I think
> the relative badness information is worthwhile.

I will admit to coming from an "if you want a single stream to go faster buy the 
next higher speed NIC" point of view, which means I pretty much lump all the 
degrees of reordering badness together.

The relative badness though is likely a _very_ broad space which couldn't be 
covered adequately in just a paragraph or two.  Notice how long my email 
describing my one experiment ended-up.

For example, I suspect, but have not verified that the one way one might get 
minimal reordering with many to one would be to have a sender with the many 
interfaces slow enough to not be able to get ahead of the sum of the NICs in the 
bond, so the transmit queues all remain at 0, coupled perhaps with NICs all in 
equal-speed and equal-feed I/O slots.

Start to be able to keep ahead of one or more of the NICs and soon we are 
starting along a rather long continuum which includes whether there are other 
concurrent connections, the distribution of send() sized by the applications, 
whether or not various offloads are enabled etc etc etc...

>>Also, since balance-rr is strictly an outbound policy, does case three
>>even enter into it - as you say, that will be up to the switch, which will
>>be doing whatever it was told or felt like doing regardless of balance-rr
>>on the bond in the host.
> 
> 
> 	Point three provides an answer to a question I've been asked
> pretty regularly by customers, so I think it's good information.

But since it isn't specific to balance_rr it would seem better placed in a 
"Switch Considerations" or "Inbound Considerations" section?

>>Even better would be to be able to start to move away from "etherchannel"
>>towards the de jure standard's terms, whatever the heck they are :)
> 
> 
> 	I believe that EtherChannel is the standard term for what we're
> talking about here, but it's a Cisco trademark.  I'd guess that most
> switch vendors don't come right out and call their "EtherChannel(tm)
> compatible" mode exactly that; they call it something else, but it's
> still meant to be compatible with EtherChannel.

Well, that assumes that many switch vendors are still including EtherChannel.  I 
know of at least one non-trivial switch vendor which has consolidated on 
LACP/802.3ad.  When that vendor was supporting EtherChannel, they called it such.

rick jones

^ permalink raw reply

* [possibly OT] for_each_netdev() in 2.6.23-gitX / 2.6.24-rc1-gitY breaks Cisco VPN client
From: Alessandro Suardi @ 2007-10-31  0:35 UTC (permalink / raw)
  To: linux-kernel; +Cc: netdev

It's been a while I noticed, but I thought someone would as usual
 cook up some fix, while I don't even see the issue been reported...
 if this isn't a Linux kernel/net issue just drop my email, thanks.

Error message during cisco_vpn.ko build:

/download/linux/net/vpnclient/interceptor.c:345:23: error: macro
"for_each_netdev" requires 2 arguments, but only 1 given

 seems like for_each_netdev() now also uses init_net. If there is
 an alternative and somebody could point me to that, it'd be great,
 as understanding the issue is well out of my grasp.

Patching up the vpnclient source to use init_net gets me to depmod
 complaining it's not allowed to use a GPL-only symbol (init_net)
 in a proprietary module. If this is meant to be - fine, and apologies
 for the waste of bandwidth; but if this is simply an unwanted side
 effect of the recent changes, perhaps it's a good idea to have it
 at least reported.

--alessandro

 "you feel the sweet breath of time
  it's whispering, its truth not mine"

   (Interpol, 'No I In Threesome')

^ permalink raw reply

* Re: [PATCH] remove claim balance_rr won't reorder on many to one
From: Jay Vosburgh @ 2007-10-31  0:22 UTC (permalink / raw)
  To: Rick Jones; +Cc: netdev
In-Reply-To: <4727AC42.2060709@hp.com>


Rick Jones <rick.jones2@hp.com> wrote:

>I have to wonder if the full description of the different versions of
>being a little bit pregnant is worth it.  Just saying that using
>balance-rr will result in reordering seems much more simple to comprehend.

	True, but the different configurations produce very different
levels of reordering.

	There seem to be users out there trying to use balance-rr to
maximize single stream TCP throughput (even with reordering), so I think
the relative badness information is worthwhile.

>Also, since balance-rr is strictly an outbound policy, does case three
>even enter into it - as you say, that will be up to the switch, which will
>be doing whatever it was told or felt like doing regardless of balance-rr
>on the bond in the host.

	Point three provides an answer to a question I've been asked
pretty regularly by customers, so I think it's good information.

[...]
>I'm not really all that tied to that part of the change - it is there
>because I noticed in one of the HP ITRC forums someone talking about a
>switch (Cisco?) where trunking meant something with vlans rather than
>aggregation.

	In Ciscoville, switch ports can be configured as either "access"
or "trunk."  A trunk port accepts all VLANs, an access port is tied to a
specific VLAN (simplifying some here).  The Cisco documentation uses the
term EtherChannel to descibe the link aggregation system we're talking
about here in reference to bonding's balance-rr mode.

>Even better would be to be able to start to move away from "etherchannel"
>towards the de jure standard's terms, whatever the heck they are :)

	I believe that EtherChannel is the standard term for what we're
talking about here, but it's a Cisco trademark.  I'd guess that most
switch vendors don't come right out and call their "EtherChannel(tm)
compatible" mode exactly that; they call it something else, but it's
still meant to be compatible with EtherChannel.

	For bonding, this applies to the balance-rr and balance-xor
modes.

	-J

---
	-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com

^ permalink raw reply

* Re: [RFC 2/2] [IPV6] ADDRCONF: Support RFC3484 configurable address selection policy table.
From: Paul E. McKenney @ 2007-10-31  0:12 UTC (permalink / raw)
  To: YOSHIFUJI Hideaki / 吉藤英明; +Cc: netdev
In-Reply-To: <20071030.145254.120595012.yoshfuji@linux-ipv6.org>

On Tue, Oct 30, 2007 at 02:52:54PM +0900, YOSHIFUJI Hideaki / 吉藤英明 wrote:

Looks good from an RCU perspective.  A couple questions below about
hlist_for_each_entry_safe().

							Thanx, Paul

> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> ---
>  include/linux/if_addrlabel.h |   55 ++++
>  include/linux/rtnetlink.h    |    7 +
>  include/net/addrconf.h       |    8 +
>  net/ipv6/Makefile            |    1 +
>  net/ipv6/addrconf.c          |   40 +---
>  net/ipv6/addrlabel.c         |  566 ++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 646 insertions(+), 31 deletions(-)
> 
> diff --git a/include/linux/if_addrlabel.h b/include/linux/if_addrlabel.h
> new file mode 100644
> index 0000000..66978a5
> --- /dev/null
> +++ b/include/linux/if_addrlabel.h
> @@ -0,0 +1,55 @@
> +/*
> + * ifaddrlabel.h - netlink interface for address labels
> + *
> + * Copyright (C)2007 USAGI/WIDE Project,  All Rights Reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + *
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the project nor the names of its contributors
> + *    may be used to endorse or promote products derived from this software
> + *    without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + */
> +
> +#ifndef __LINUX_IF_ADDRLABEL_H
> +#define __LINUX_IF_ADDRLABEL_H
> +
> +struct ifaddrlblmsg
> +{
> +	__u8		ifal_family;		/* Address family */
> +	__u8		__ifal_reserved;	/* Reserved */
> +	__u8		ifal_prefixlen;		/* Prefix length */
> +	__u8		ifal_flags;		/* Flags */
> +	__u32		ifal_index;		/* Link index */
> +	__u32		ifal_seq;		/* sequence number */
> +};
> +
> +enum
> +{
> +	IFAL_ADDRESS = 1,
> +	IFAL_LABEL = 2,
> +	__IFAL_MAX
> +};
> +
> +#define IFAL_MAX	(__IFAL_MAX - 1)
> +
> +#endif
> diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
> index 5bf6182..9a8bf01 100644
> --- a/include/linux/rtnetlink.h
> +++ b/include/linux/rtnetlink.h
> @@ -100,6 +100,13 @@ enum {
>  	RTM_NEWNDUSEROPT = 68,
>  #define RTM_NEWNDUSEROPT RTM_NEWNDUSEROPT
> 
> +	RTM_NEWADDRLABEL = 72,
> +#define RTM_NEWADDRLABEL RTM_NEWADDRLABEL
> +	RTM_DELADDRLABEL,
> +#define RTM_NEWADDRLABEL RTM_NEWADDRLABEL
> +	RTM_GETADDRLABEL,
> +#define RTM_GETADDRLABEL RTM_GETADDRLABEL
> +
>  	__RTM_MAX,
>  #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
>  };
> diff --git a/include/net/addrconf.h b/include/net/addrconf.h
> index 33b593e..bccc2fe 100644
> --- a/include/net/addrconf.h
> +++ b/include/net/addrconf.h
> @@ -84,6 +84,14 @@ extern void			addrconf_leave_solict(struct inet6_dev *idev,
>  					struct in6_addr *addr);
> 
>  /*
> + *	IPv6 Address Label subsystem (addrlabel.c)
> + */
> +extern int			ipv6_addr_label_init(void);
> +extern void			ipv6_addr_label_rtnl_register(void);
> +extern u32			ipv6_addr_label(const struct in6_addr *addr,
> +						int type, int ifindex);
> +
> +/*
>   *	multicast prototypes (mcast.c)
>   */
>  extern int ipv6_sock_mc_join(struct sock *sk, int ifindex, 
> diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
> index 87c23a7..5ffa980 100644
> --- a/net/ipv6/Makefile
> +++ b/net/ipv6/Makefile
> @@ -5,6 +5,7 @@
>  obj-$(CONFIG_IPV6) += ipv6.o
> 
>  ipv6-objs :=	af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
> +		addrlabel.o \
>  		route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
>  		raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
>  		exthdrs.o sysctl_net_ipv6.o datagram.o \
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 8b408b7..5b6553f 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -876,36 +876,6 @@ static inline int ipv6_saddr_preferred(int type)
>  	return 0;
>  }
> 
> -/* static matching label */
> -static inline int ipv6_addr_label(const struct in6_addr *addr, int type,
> -				  int ifindex)
> -{
> - /*
> -  * 	prefix (longest match)	label
> -  * 	-----------------------------
> -  * 	::1/128			0
> -  * 	::/0			1
> -  * 	2002::/16		2
> -  * 	::/96			3
> -  * 	::ffff:0:0/96		4
> -  *	fc00::/7		5
> -  * 	2001::/32		6
> -  */
> -	if (type & IPV6_ADDR_LOOPBACK)
> -		return 0;
> -	else if (type & IPV6_ADDR_COMPATv4)
> -		return 3;
> -	else if (type & IPV6_ADDR_MAPPED)
> -		return 4;
> -	else if (addr->s6_addr32[0] == htonl(0x20010000))
> -		return 6;
> -	else if (addr->s6_addr16[0] == htons(0x2002))
> -		return 2;
> -	else if ((addr->s6_addr[0] & 0xfe) == 0xfc)
> -		return 5;
> -	return 1;
> -}
> -
>  int ipv6_dev_get_saddr(struct net_device *daddr_dev,
>  		       struct in6_addr *daddr, struct in6_addr *saddr)
>  {
> @@ -4182,7 +4152,13 @@ EXPORT_SYMBOL(unregister_inet6addr_notifier);
> 
>  int __init addrconf_init(void)
>  {
> -	int err = 0;
> +	int err;
> +
> +	if ((err = ipv6_addr_label_init()) < 0) {
> +		printk(KERN_CRIT "IPv6 Addrconf: cannot initialize default policy table: %d.\n",
> +			err);
> +		return err;
> +	}
> 
>  	/* The addrconf netdev notifier requires that loopback_dev
>  	 * has it's ipv6 private information allocated and setup
> @@ -4233,6 +4209,8 @@ int __init addrconf_init(void)
>  	__rtnl_register(PF_INET6, RTM_GETMULTICAST, NULL, inet6_dump_ifmcaddr);
>  	__rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr);
> 
> +	ipv6_addr_label_rtnl_register();
> +
>  #ifdef CONFIG_SYSCTL
>  	addrconf_sysctl.sysctl_header =
>  		register_sysctl_table(addrconf_sysctl.addrconf_root_dir);
> diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
> new file mode 100644
> index 0000000..719e785
> --- /dev/null
> +++ b/net/ipv6/addrlabel.c
> @@ -0,0 +1,566 @@
> +/*
> + * IPv6 Address Label subsystem
> + * for the IPv6 "Default" Source Address Selection
> + *
> + * Copyright (C)2007 USAGI/WIDE Project
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +/*
> + * Author:
> + * 	YOSHIFUJI Hideaki @ USAGI/WIDE Project <yoshfuji@linux-ipv6.org>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/rcupdate.h>
> +#include <linux/in6.h>
> +#include <net/addrconf.h>
> +#include <linux/if_addrlabel.h>
> +#include <linux/netlink.h>
> +#include <linux/rtnetlink.h>
> +
> +#if 0
> +#define ADDRLABEL(x...) printk(x)
> +#else
> +#define ADDRLABEL(x...) do { ; } while(0)
> +#endif
> +
> +/*
> + * Policy Table
> + */
> +struct ip6addrlbl_entry
> +{
> +	struct in6_addr prefix;
> +	int prefixlen;
> +	int ifindex;
> +	int addrtype;
> +	u32 label;
> +	struct hlist_node list;
> +	atomic_t refcnt;
> +	struct rcu_head rcu;
> +};
> +
> +static struct ip6addrlbl_table
> +{
> +	struct hlist_head head;
> +	spinlock_t lock;
> +	u32 seq;
> +} ip6addrlbl_table;
> +
> +/*
> + * Default policy table (RFC3484 + extensions)
> + *
> + * prefix		addr_type	label
> + * -------------------------------------------------------------------------
> + * ::1/128		LOOPBACK	0
> + * ::/0			N/A		1
> + * 2002::/16		N/A		2
> + * ::/96		COMPATv4	3
> + * ::ffff:0:0/96	V4MAPPED	4
> + * fc00::/7		N/A		5		ULA (RFC 4193)
> + * 2001::/32		N/A		6		Teredo (RFC 4380)
> + *
> + * Note: 0xffffffff is used if we do not have any policies.
> + */
> +
> +#define IPV6_ADDR_LABEL_DEFAULT	0xffffffffUL
> +
> +static const __initdata struct ip6addrlbl_init_table
> +{
> +	const struct in6_addr *prefix;
> +	int prefixlen;
> +	u32 label;
> +} ip6addrlbl_init_table[] = {
> +	{	/* ::/0 */
> +		.prefix = &in6addr_any,
> +		.label = 1,
> +	},{	/* fc00::/7 */
> +		.prefix = &(struct in6_addr){{{ 0xfc }}},
> +		.prefixlen = 7,
> +		.label = 5,
> +	},{	/* 2002::/16 */
> +		.prefix = &(struct in6_addr){{{ 0x20, 0x02 }}},
> +		.prefixlen = 16,
> +		.label = 2,
> +	},{	/* 2001::/32 */
> +		.prefix = &(struct in6_addr){{{ 0x20, 0x01 }}},
> +		.prefixlen = 32,
> +		.label = 6,
> +	},{	/* ::ffff:0:0 */
> +		.prefix = &(struct in6_addr){{{ [10] = 0xff, [11] = 0xff }}},
> +		.prefixlen = 96,
> +		.label = 4,
> +	},{	/* ::/96 */
> +		.prefix = &in6addr_any,
> +		.prefixlen = 96,
> +		.label = 3,
> +	},{	/* ::1/128 */
> +		.prefix = &in6addr_loopback,
> +		.prefixlen = 128,
> +		.label = 0,
> +	}
> +};
> +
> +/* Object management */
> +static inline void ip6addrlbl_free(struct ip6addrlbl_entry *p)
> +{
> +	kfree(p);
> +}
> +
> +static inline int ip6addrlbl_hold(struct ip6addrlbl_entry *p)
> +{
> +	return atomic_inc_not_zero(&p->refcnt);
> +}
> +
> +static inline void ip6addrlbl_put(struct ip6addrlbl_entry *p)
> +{
> +	if (atomic_dec_and_test(&p->refcnt))
> +		ip6addrlbl_free(p);
> +}
> +
> +static void ip6addrlbl_free_rcu(struct rcu_head *h)
> +{
> +	ip6addrlbl_free(container_of(h, struct ip6addrlbl_entry, rcu));
> +}
> +
> +/* Find label */
> +static int __ip6addrlbl_match(struct ip6addrlbl_entry *p,
> +			      const struct in6_addr *addr,
> +			      int addrtype, int ifindex)
> +{
> +	if (p->ifindex && p->ifindex != ifindex)
> +		return 0;
> +	if (p->addrtype && p->addrtype != addrtype)
> +		return 0;
> +	if (!ipv6_prefix_equal(addr, &p->prefix, p->prefixlen))
> +		return 0;
> +	return 1;
> +}
> +
> +static struct ip6addrlbl_entry *__ipv6_addr_label(const struct in6_addr *addr,
> +						  int type, int ifindex)
> +{
> +	struct hlist_node *pos;
> +	struct ip6addrlbl_entry *p;
> +	hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) {
> +		if (__ip6addrlbl_match(p, addr, type, ifindex))
> +			return p;
> +	}
> +	return NULL;
> +}
> +
> +u32 ipv6_addr_label(const struct in6_addr *addr, int type, int ifindex)
> +{
> +	u32 label;
> +	struct ip6addrlbl_entry *p;
> +
> +	type &= IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK;
> +
> +	rcu_read_lock();
> +	p = __ipv6_addr_label(addr, type, ifindex);
> +	label = p ? p->label : IPV6_ADDR_LABEL_DEFAULT;
> +	rcu_read_unlock();
> +
> +	ADDRLABEL(KERN_DEBUG "%s(addr=" NIP6_FMT ", type=%d, ifindex=%d) => %08x\n",
> +			__FUNCTION__,
> +			NIP6(*addr), type, ifindex,
> +			label);
> +
> +	return label;
> +}
> +
> +/* allocate one entry */
> +struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix,
> +					  int prefixlen, int ifindex,
> +					  u32 label)
> +{
> +	struct ip6addrlbl_entry *newp;
> +	int addrtype;
> +
> +	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u)\n",
> +			__FUNCTION__,
> +			NIP6(*prefix), prefixlen,
> +			ifindex,
> +			(unsigned int)label);
> +
> +	addrtype = ipv6_addr_type(prefix) & (IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK);
> +
> +	switch (addrtype) {
> +	case IPV6_ADDR_MAPPED:
> +		if (prefixlen > 96)
> +			return ERR_PTR(-EINVAL);
> +		if (prefixlen < 96)
> +			addrtype = 0;
> +		break;
> +	case IPV6_ADDR_COMPATv4:
> +		if (prefixlen != 96)
> +			addrtype = 0;
> +		break;
> +	case IPV6_ADDR_LOOPBACK:
> +		if (prefixlen != 128)
> +			addrtype = 0;
> +		break;
> +	}
> +
> +	newp = kmalloc(sizeof(*newp), GFP_KERNEL);
> +	if (!newp)
> +		return ERR_PTR(-ENOMEM);
> +
> +	ipv6_addr_prefix(&newp->prefix, prefix, prefixlen);
> +	newp->prefixlen = prefixlen;
> +	newp->ifindex = ifindex;
> +	newp->addrtype = addrtype;
> +	newp->label = label;
> +	INIT_HLIST_NODE(&newp->list);
> +	atomic_set(&newp->refcnt, 1);
> +	return newp;
> +}
> +
> +/* add a label */
> +int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace)
> +{
> +	int ret = 0;
> +
> +	ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n",
> +			__FUNCTION__,
> +			newp, replace);
> +
> +	if (hlist_empty(&ip6addrlbl_table.head)) {
> +		hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head);
> +	} else {
> +		struct hlist_node *pos, *n;
> +		struct ip6addrlbl_entry *p = NULL;
> +		hlist_for_each_entry_safe(p, pos, n,

Why not list_for_each_entry(), given that you exit the look when you
do the replacement below?

> +					  &ip6addrlbl_table.head, list) {
> +			if (p->prefixlen == newp->prefixlen &&
> +			    p->ifindex == newp->ifindex &&
> +			    ipv6_addr_equal(&p->prefix, &newp->prefix)) {
> +				if (!replace) {
> +					ret = -EEXIST;
> +					goto out;
> +				}
> +				hlist_replace_rcu(&p->list, &newp->list);
> +				ip6addrlbl_put(p);
> +				call_rcu(&p->rcu, ip6addrlbl_free_rcu);

Side note:  if you didn't have a "goto out" here, then this would
be vulnerable to the following sequence of events in a CONFIG_PREEMPT_RT
kernel:

1.	Preemption occurs here (cannot happen in CONFIG_PREEMPT or
	vanilla kernel, but can happen in -rt).

2.	Grace period completes.

3.	ip6addrlbl_free_rcu() frees up the current element.

4.	This element is allocated and used for some entirely different
	structure.

5.	This task resumes execution, and the hlist_for_each_entry_safe()
	uses a pointer to the newly repurposed block of memory.  Oops!

> +				goto out;
> +			} else if ((p->prefixlen == newp->prefixlen && !p->ifindex) ||
> +				   (p->prefixlen < newp->prefixlen)) {
> +				hlist_add_before_rcu(&newp->list, &p->list);
> +				goto out;
> +			}
> +		}
> +		hlist_add_after_rcu(&p->list, &newp->list);
> +	}
> +out:
> +	if (!ret)
> +		ip6addrlbl_table.seq++;
> +	return ret;
> +}
> +
> +/* add a label */
> +int ip6addrlbl_add(const struct in6_addr *prefix, int prefixlen,
> +		       int ifindex, u32 label, int replace)
> +{
> +	struct ip6addrlbl_entry *newp;
> +	int ret = 0;
> +
> +	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n",
> +			__FUNCTION__,
> +			NIP6(*prefix), prefixlen,
> +			ifindex,
> +			(unsigned int)label,
> +			replace);
> +
> +	newp = ip6addrlbl_alloc(prefix, prefixlen, ifindex, label);
> +	if (IS_ERR(newp))
> +		return PTR_ERR(newp);
> +	spin_lock(&ip6addrlbl_table.lock);
> +	ret = __ip6addrlbl_add(newp, replace);
> +	spin_unlock(&ip6addrlbl_table.lock);
> +	if (ret)
> +		ip6addrlbl_free(newp);
> +	return ret;
> +}
> +
> +/* remove a label */
> +int __ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen,
> +			  int ifindex)
> +{
> +	struct ip6addrlbl_entry *p = NULL;
> +	struct hlist_node *pos, *n;
> +	int ret = -ESRCH;
> +
> +	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n",
> +			__FUNCTION__,
> +			NIP6(*prefix), prefixlen,
> +			ifindex);
> +
> +	hlist_for_each_entry_safe(p, pos, n, &ip6addrlbl_table.head, list) {

Again, why not list_for_each_entry(), given that you exit the look when
you do the replacement below?

> +		if (p->prefixlen == prefixlen &&
> +		    p->ifindex == ifindex &&
> +		    ipv6_addr_equal(&p->prefix, prefix)) {
> +			hlist_del_rcu(&p->list);
> +			ip6addrlbl_put(p);
> +			call_rcu(&p->rcu, ip6addrlbl_free_rcu);
> +			ret = 0;
> +			break;
> +		}
> +	}
> +	return ret;
> +}
> +
> +int ip6addrlbl_del(const struct in6_addr *prefix, int prefixlen,
> +		       int ifindex)
> +{
> +	struct in6_addr prefix_buf;
> +	int ret;
> +
> +	ADDRLABEL(KERN_DEBUG "%s(prefix=" NIP6_FMT ", prefixlen=%d, ifindex=%d)\n",
> +			__FUNCTION__,
> +			NIP6(*prefix), prefixlen,
> +			ifindex);
> +
> +	ipv6_addr_prefix(&prefix_buf, prefix, prefixlen);
> +	spin_lock(&ip6addrlbl_table.lock);
> +	ret = __ip6addrlbl_del(&prefix_buf, prefixlen, ifindex);
> +	spin_unlock(&ip6addrlbl_table.lock);
> +	return ret;
> +}
> +
> +/* add default label */
> +static __init int ip6addrlbl_init(void)
> +{
> +	int err = 0;
> +	int i;
> +
> +	ADDRLABEL(KERN_DEBUG "%s()\n", __FUNCTION__);
> +
> +	for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) {
> +		int ret = ip6addrlbl_add(ip6addrlbl_init_table[i].prefix,
> +					 ip6addrlbl_init_table[i].prefixlen,
> +					 0,
> +					 ip6addrlbl_init_table[i].label, 0);
> +		/* XXX: should we free all rules when we catch an error? */
> +		if (ret && (!err || err != -ENOMEM))
> +			err = ret;
> +	}
> +	return err;
> +}
> +
> +int __init ipv6_addr_label_init(void)
> +{
> +	spin_lock_init(&ip6addrlbl_table.lock);
> +
> +	return ip6addrlbl_init();
> +}
> +
> +static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
> +	[IFAL_ADDRESS]		= { .len = sizeof(struct in6_addr), },
> +	[IFAL_LABEL]		= { .len = sizeof(u32), },
> +};
> +
> +static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,
> +			     void *arg)
> +{
> +	struct ifaddrlblmsg *ifal;
> +	struct nlattr *tb[IFAL_MAX+1];
> +	struct in6_addr *pfx;
> +	u32 label;
> +	int err = 0;
> +
> +	err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy);
> +	if (err < 0)
> +		return err;
> +
> +	ifal = nlmsg_data(nlh);
> +
> +	if (ifal->ifal_family != AF_INET6 ||
> +	    ifal->ifal_prefixlen > 128)
> +		return -EINVAL;
> +
> +	if (ifal->ifal_index &&
> +	    !__dev_get_by_index(&init_net, ifal->ifal_index))
> +		return -EINVAL;
> +
> +	if (!tb[IFAL_ADDRESS])
> +		return -EINVAL;
> +
> +	pfx = nla_data(tb[IFAL_ADDRESS]);
> +	if (!pfx)
> +		return -EINVAL;
> +
> +	if (!tb[IFAL_LABEL])
> +		return -EINVAL;
> +	label = nla_get_u32(tb[IFAL_LABEL]);
> +	if (label == IPV6_ADDR_LABEL_DEFAULT)
> +		return -EINVAL;
> +
> +	switch(nlh->nlmsg_type) {
> +	case RTM_NEWADDRLABEL:
> +		err = ip6addrlbl_add(pfx, ifal->ifal_prefixlen,
> +				     ifal->ifal_index, label,
> +				     nlh->nlmsg_flags & NLM_F_REPLACE);
> +		break;
> +	case RTM_DELADDRLABEL:
> +		err = ip6addrlbl_del(pfx, ifal->ifal_prefixlen,
> +				     ifal->ifal_index);
> +		break;
> +	default:
> +		err = -EOPNOTSUPP;
> +	}
> +	return err;
> +}
> +
> +static inline void ip6addrlbl_putmsg(struct nlmsghdr *nlh,
> +				     int prefixlen, int ifindex, u32 lseq)
> +{
> +	struct ifaddrlblmsg *ifal = nlmsg_data(nlh);
> +	ifal->ifal_family = AF_INET6;
> +	ifal->ifal_prefixlen = prefixlen;
> +	ifal->ifal_flags = 0;
> +	ifal->ifal_index = ifindex;
> +	ifal->ifal_seq = lseq;
> +};
> +
> +static int ip6addrlbl_fill(struct sk_buff *skb,
> +			   struct ip6addrlbl_entry *p,
> +			   u32 lseq,
> +			   u32 pid, u32 seq, int event,
> +			   unsigned int flags)
> +{
> +	struct nlmsghdr *nlh = nlmsg_put(skb, pid, seq, event,
> +					 sizeof(struct ifaddrlblmsg), flags);
> +	if (!nlh)
> +		return -EMSGSIZE;
> +
> +	ip6addrlbl_putmsg(nlh, p->prefixlen, p->ifindex, lseq);
> +
> +	if (nla_put(skb, IFAL_ADDRESS, 16, &p->prefix) < 0 ||
> +	    nla_put_u32(skb, IFAL_LABEL, p->label) < 0) {
> +		nlmsg_cancel(skb, nlh);
> +		return -EMSGSIZE;
> +	}
> +
> +	return nlmsg_end(skb, nlh);
> +}
> +
> +static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb)
> +{
> +	struct ip6addrlbl_entry *p;
> +	struct hlist_node *pos;
> +	int idx = 0, s_idx = cb->args[0];
> +	int err;
> +
> +	rcu_read_lock();
> +	hlist_for_each_entry_rcu(p, pos, &ip6addrlbl_table.head, list) {
> +		if (idx >= s_idx) {
> +			if ((err = ip6addrlbl_fill(skb, p,
> +						   ip6addrlbl_table.seq,
> +						   NETLINK_CB(cb->skb).pid,
> +						   cb->nlh->nlmsg_seq,
> +						   RTM_NEWADDRLABEL,
> +						   NLM_F_MULTI)) <= 0)
> +				break;
> +		}
> +		idx++;
> +	}
> +	rcu_read_unlock();
> +	cb->args[0] = idx;
> +	return skb->len;
> +}
> +
> +static inline int ip6addrlbl_msgsize(void)
> +{
> +	return (NLMSG_ALIGN(sizeof(struct ifaddrlblmsg))
> +		+ nla_total_size(16)	/* IFAL_ADDRESS */
> +		+ nla_total_size(4)	/* IFAL_LABEL */
> +	);
> +}
> +
> +static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh,
> +			  void *arg)
> +{
> +	struct ifaddrlblmsg *ifal;
> +	struct nlattr *tb[IFAL_MAX+1];
> +	struct in6_addr *addr;
> +	u32 lseq;
> +	int err = 0;
> +	struct ip6addrlbl_entry *p;
> +	struct sk_buff *skb;
> +
> +	err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy);
> +	if (err < 0)
> +		return err;
> +
> +	ifal = nlmsg_data(nlh);
> +
> +	if (ifal->ifal_family != AF_INET6 ||
> +	    ifal->ifal_prefixlen != 128)
> +		return -EINVAL;
> +
> +	if (ifal->ifal_index &&
> +	    !__dev_get_by_index(&init_net, ifal->ifal_index))
> +		return -EINVAL;
> +
> +	if (!tb[IFAL_ADDRESS])
> +		return -EINVAL;
> +
> +	addr = nla_data(tb[IFAL_ADDRESS]);
> +	if (!addr)
> +		return -EINVAL;
> +
> +	rcu_read_lock();
> +	p = __ipv6_addr_label(addr, ipv6_addr_type(addr), ifal->ifal_index);
> +	if (p && ip6addrlbl_hold(p))
> +		p = NULL;
> +	lseq = ip6addrlbl_table.seq;
> +	rcu_read_unlock();
> +
> +	if (!p) {
> +		err = -ESRCH;
> +		goto out;
> +	}
> +
> +	if (!(skb = nlmsg_new(ip6addrlbl_msgsize(), GFP_KERNEL))) {
> +		ip6addrlbl_put(p);
> +		return -ENOBUFS;
> +	}
> +
> +	err = ip6addrlbl_fill(skb, p, lseq,
> +			      NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
> +			      RTM_NEWADDRLABEL, 0);
> +
> +	ip6addrlbl_put(p);
> +
> +	if (err < 0) {
> +		WARN_ON(err == -EMSGSIZE);
> +		kfree_skb(skb);
> +		goto out;
> +	}
> +
> +	err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
> +out:
> +	return err;
> +}
> +
> +void __init addrlabel_rtnl_register(void)
> +{
> +	__rtnl_register(PF_INET6, RTM_NEWADDRLABEL, ip6addrlbl_newdel, NULL);
> +	__rtnl_register(PF_INET6, RTM_DELADDRLABEL, ip6addrlbl_newdel, NULL);
> +	__rtnl_register(PF_INET6, RTM_GETADDRLABEL, ip6addrlbl_get, ip6addrlbl_dump);
> +}
> +
> -- 
> 1.4.4.4
> 
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: recent sysfs changes cause lots of network device errors
From: Rick Jones @ 2007-10-31  0:02 UTC (permalink / raw)
  To: Greg KH; +Cc: Stephen Hemminger, Tejun Heo, David S. Miller, netdev,
	Kay Sievers
In-Reply-To: <20071030224043.GA6612@kroah.com>

> Well, this was a bug that no one caught in -mm as we all seem to be
> running with CONFIG_SYSFS_DEPRECATED disabled.  There was a long
> discussion on lkml last week, and here's the patch that should fix it
> that is going to Linus in a day or so (it's in my tree, but I'm supposed
> to be on vacation right now...)
> 
> Let me know if this works for you or not.

I don't know if it worked for Stephen, but it certainly worked to get rid of the 
last three rename-induced stack traces on my system.

rick jones

^ permalink raw reply

* Re: [PATCH] ehea: add kexec support
From: Michael Ellerman @ 2007-10-30 22:50 UTC (permalink / raw)
  To: Christoph Raisch
  Cc: Jan-Bernd Themann, Jeff Garzik, linux-kernel, linux-ppc,
	Marcus Eder, netdev, ossthema, Stefan Roscher, Thomas Q Klein
In-Reply-To: <OF79E7ACE7.5D0488CE-ONC1257384.002E58C0-C1257384.002F8561@de.ibm.com>

[-- Attachment #1: Type: text/plain, Size: 957 bytes --]


On Tue, 2007-10-30 at 09:39 +0100, Christoph Raisch wrote:
> 
> Michael Ellerman <michael@ellerman.id.au> wrote on 28.10.2007 23:32:17:
> >
> >
> > How do you plan to support kdump?
> >
> 
> When kexec is fully supported kdump should work out of the box
> as for any other ethernet card (if you load the right eth driver).
> There's nothing specific to kdump you have to handle in
> ethernet device drivers.
> Hope I didn't miss anything here...

Perhaps. When we kdump the kernel does not call the reboot notifiers, so
the code Jan-Bernd just added won't get called. So the eHEA resources
won't be freed. When the kdump kernel tries to load the eHEA driver what
will happen?

cheers

-- 
Michael Ellerman
OzLabs, IBM Australia Development Lab

wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ 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