* 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 1/14 v2] nes: module and device initialization
From: Roland Dreier @ 2007-10-31 5:21 UTC (permalink / raw)
To: Glenn Grundstrom; +Cc: ewg, general, netdev
In-Reply-To: <5E701717F2B2ED4EA60F87C8AA57B7CC078C9670@venom2>
> Thanks Roland. Let me know when you have your branch ready.
OK, I pushed out a "neteffect" branch at
git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
This has the driver from your git tree plus some compile fixes and
cleanups (added as separate commits, so you can see what I did). If
it suits you, let's work against that tree to continue cleaning things
up -- you can send me patches or git pull requests to pick up new things.
- R.
^ permalink raw reply
* [PATCH] af_key: suppress a warning for 64k pages.
From: Stephen Rothwell @ 2007-10-31 5:24 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-kernel
In-Reply-To: <20071030.214219.256397507.davem@davemloft.net>
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 | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
This version gets rid of the warning without the ugliness of ifdefs.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 7969f8a..266f112 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -395,9 +395,9 @@ static inline int pfkey_sec_ctx_len(struct sadb_x_sec_ctx *sec_ctx)
static inline int verify_sec_ctx_len(void *p)
{
struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p;
- int len;
+ int len = sec_ctx->sadb_x_ctx_len;
- if (sec_ctx->sadb_x_ctx_len > PAGE_SIZE)
+ if (len > PAGE_SIZE)
return -EINVAL;
len = pfkey_sec_ctx_len(sec_ctx);
--
1.5.3.4
^ permalink raw reply related
* Re: [PATCH]: Fix networking scatterlist regressions.
From: Rusty Russell @ 2007-10-31 6:06 UTC (permalink / raw)
To: David Miller; +Cc: netdev, herbert, jens.axboe
In-Reply-To: <20071030.204002.193703502.davem@davemloft.net>
On Wednesday 31 October 2007 14:40:02 David Miller wrote:
> 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 :-)
Grr, the scatterlist changes are really pissing me off. We get ugly tricky
code *and* transition pain.
I hate to suggest this, but I don't supposed there's a chance we can revert it
for 2.6.24 and do something cleaner for 2.6.25?
Rusty.
^ permalink raw reply
* Re: [PATCH]: Fix networking scatterlist regressions.
From: David Miller @ 2007-10-31 6:44 UTC (permalink / raw)
To: rusty; +Cc: netdev, herbert, jens.axboe
In-Reply-To: <200710311706.33142.rusty@rustcorp.com.au>
From: Rusty Russell <rusty@rustcorp.com.au>
Date: Wed, 31 Oct 2007 17:06:32 +1100
> On Wednesday 31 October 2007 14:40:02 David Miller wrote:
> > 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 :-)
>
> Grr, the scatterlist changes are really pissing me off. We get ugly tricky
> code *and* transition pain.
>
> I hate to suggest this, but I don't supposed there's a chance we can revert it
> for 2.6.24 and do something cleaner for 2.6.25?
I will hit you on the head with a hammer if this happens after all
the debugging and work I've put into fixing things so far. :-/
Just like this: Plonk!
^ permalink raw reply
* Re: [PATCH] af_key: suppress a warning for 64k pages.
From: David Miller @ 2007-10-31 6:58 UTC (permalink / raw)
To: sfr; +Cc: netdev, linux-kernel
In-Reply-To: <20071031162452.fcea4431.sfr@canb.auug.org.au>
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Wed, 31 Oct 2007 16:24:52 +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>
Applied, thanks Stephen.
^ permalink raw reply
* Re: [PATCH v2] using mii-bitbang on different processor ports
From: Sergej Stepanov @ 2007-10-31 7:30 UTC (permalink / raw)
To: linuxppc-dev, netdev, jgarzik
In-Reply-To: <472776AE.2060009@freescale.com>
Am Dienstag, den 30.10.2007, 13:23 -0500 schrieb Scott Wood:
> Sergej Stepanov wrote:
> > + if( !of_address_to_resource(np, 1, &res[1])) {
>
> The spacing is still wrong.
>
> > - iounmap(bitbang->dir);
> > + if ( bitbang->mdio.dir != bitbang->mdc.dir)
> > + iounmap(bitbang->mdio.dir);
> > + iounmap(bitbang->mdc.dir);
>
> And here.
>
> -Scott
Oh, sorry.
--
Sergej I. Stepanov
E-PA
IDS GmbH
Nobelstr. 18, Zim. 2.1.05
D-76275 Ettlingen
T +49 (0) 72 43/2 18-615
F +49 (0) 72 43/2 18-400
Email: <Sergej.Stepanov@ids.de>
<http://www.ids.de>
Geschäftsführer: Norbert Wagner, Friedrich Abriß
Sitz der Gesellschaft: Ettlingen
Amtsgericht Mannheim HRB 362503
^ permalink raw reply
* Re: [PATCH]: Fix networking scatterlist regressions.
From: Jens Axboe @ 2007-10-31 7:32 UTC (permalink / raw)
To: David Miller; +Cc: netdev, herbert, rusty
In-Reply-To: <20071030.204002.193703502.davem@davemloft.net>
On Tue, Oct 30 2007, David Miller wrote:
>
> 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.
I fully agree, lets just change sg_mark_end() to NOT overwrite a stored
page there. The current interface isn't nice and can't be used after
filling the sg table, which is what users would want. I've added such a
patch to the sg repo.
>From 5a0347663f51850eb52b89c4dcf6a714ea8d3965 Mon Sep 17 00:00:00 2001
From: Jens Axboe <jens.axboe@oracle.com>
Date: Wed, 31 Oct 2007 08:31:23 +0100
Subject: [PATCH] [SG] Remove __sg_mark_end()
Make sg_mark_end() NOT overwrite the page link. Then it can be used
after filling the sg table, which is what users want. That means that
__sg_mark_end() is no longer useful, so kill it.
It's important the sg entries be initialized before using sg_mark_end(),
so also add a debug check to catch use-before-init.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
---
block/ll_rw_blk.c | 2 +-
include/linux/scatterlist.h | 10 ++++------
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index e948407..fdc0707 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1369,7 +1369,7 @@ new_segment:
} /* segments in rq */
if (sg)
- __sg_mark_end(sg);
+ sg_mark_end(sg);
return nsegs;
}
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index d5e1876..aa97954 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -195,13 +195,11 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
* Marks the last entry as the termination point for sg_next()
*
**/
-static inline void sg_mark_end(struct scatterlist *sgl, unsigned int nents)
-{
- sgl[nents - 1].page_link = 0x02;
-}
-
-static inline void __sg_mark_end(struct scatterlist *sg)
+static inline void sg_mark_end(struct scatterlist *sg)
{
+#ifdef CONFIG_DEBUG_SG
+ BUG_ON(sg->sg_magic != SG_MAGIC);
+#endif
sg->page_link |= 0x02;
}
--
1.5.3.GIT
--
Jens Axboe
^ permalink raw reply related
* Re: [PATCH]: Fix networking scatterlist regressions.
From: David Miller @ 2007-10-31 7:43 UTC (permalink / raw)
To: jens.axboe; +Cc: netdev, herbert, rusty
In-Reply-To: <20071031073207.GA5059@kernel.dk>
From: Jens Axboe <jens.axboe@oracle.com>
Date: Wed, 31 Oct 2007 08:32:07 +0100
> [SG] Remove __sg_mark_end()
>
> Make sg_mark_end() NOT overwrite the page link. Then it can be used
> after filling the sg table, which is what users want. That means that
> __sg_mark_end() is no longer useful, so kill it.
>
> It's important the sg entries be initialized before using sg_mark_end(),
> so also add a debug check to catch use-before-init.
>
> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Ok, but I just pushed my changes to Linus and once those show up
you'll need to extend this patch to kill the '__' prefix from
all the rest of the calls which will be in the tree.
Thanks!
^ permalink raw reply
* Re: [PATCH]: Fix networking scatterlist regressions.
From: Jens Axboe @ 2007-10-31 7:46 UTC (permalink / raw)
To: David Miller; +Cc: netdev, herbert, rusty
In-Reply-To: <20071030.204002.193703502.davem@davemloft.net>
On Tue, Oct 30 2007, David Miller wrote:
> 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);
Hmm? These don't seem right. It also has a weird code sequence:
...
sg_mark_end(&desc->infrags[desc->fragno - 1]);
sg_mark_end(&desc->outfrags[desc->fragno - 1]);
ret = crypto_blkcipher_encrypt_iv(&desc->desc, desc->outfrags,
desc->infrags, thislen);
if (ret)
return ret;
sg_init_table(desc->infrags, 4);
sg_init_table(desc->outfrags, 4);
...
Did something go wrong there?
--
Jens Axboe
^ permalink raw reply
* Re: [PATCH]: Fix networking scatterlist regressions.
From: Jens Axboe @ 2007-10-31 7:47 UTC (permalink / raw)
To: David Miller; +Cc: netdev, herbert, rusty
In-Reply-To: <20071031.004320.175325164.davem@davemloft.net>
On Wed, Oct 31 2007, David Miller wrote:
> From: Jens Axboe <jens.axboe@oracle.com>
> Date: Wed, 31 Oct 2007 08:32:07 +0100
>
> > [SG] Remove __sg_mark_end()
> >
> > Make sg_mark_end() NOT overwrite the page link. Then it can be used
> > after filling the sg table, which is what users want. That means that
> > __sg_mark_end() is no longer useful, so kill it.
> >
> > It's important the sg entries be initialized before using sg_mark_end(),
> > so also add a debug check to catch use-before-init.
> >
> > Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
>
> Ok, but I just pushed my changes to Linus and once those show up
> you'll need to extend this patch to kill the '__' prefix from
> all the rest of the calls which will be in the tree.
>
> Thanks!
No problem, I'll base further sg_mark_end() updates on top of yours.
Just need to get that last email I sent out resolved, the
gss_krb5_crypto bits.
--
Jens Axboe
^ permalink raw reply
* Re: [PATCH]: Fix networking scatterlist regressions.
From: David Miller @ 2007-10-31 7:58 UTC (permalink / raw)
To: jens.axboe; +Cc: netdev, herbert, rusty
In-Reply-To: <20071031074621.GB5059@kernel.dk>
From: Jens Axboe <jens.axboe@oracle.com>
Date: Wed, 31 Oct 2007 08:46:21 +0100
> On Tue, Oct 30 2007, David Miller wrote:
> > @@ -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);
>
> Hmm? These don't seem right. It also has a weird code sequence:
...
> Did something go wrong there?
Yes, I fixed those up after doing some allmodconfig builds.
Here is the final patch I actually pushed to Linus:
>From 51c739d1f484b2562040a3e496dc8e1670d4e279 Mon Sep 17 00:00:00 2001
From: David S. Miller <davem@sunset.davemloft.net>
Date: Tue, 30 Oct 2007 21:29:29 -0700
Subject: [PATCH] [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..c387cf6 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 - 1]);
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..ab7cbd6 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 - 1]);
+ __sg_mark_end(&desc->outfrags[desc->fragno - 1]);
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 - 1]);
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: Eric W. Biederman @ 2007-10-31 8:03 UTC (permalink / raw)
To: benh; +Cc: Joel Becker, Linux Netdev, Linux Kernel Mailing List,
David S. Miller
In-Reply-To: <1193798124.9928.91.camel@pasglop>
Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:
> 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 :-)
Grr sorry about that, and thanks for catching this.
Eric
> 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]: Fix networking scatterlist regressions.
From: Jens Axboe @ 2007-10-31 8:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, herbert, rusty
In-Reply-To: <20071031.005802.204286555.davem@davemloft.net>
On Wed, Oct 31 2007, David Miller wrote:
> From: Jens Axboe <jens.axboe@oracle.com>
> Date: Wed, 31 Oct 2007 08:46:21 +0100
>
> > On Tue, Oct 30 2007, David Miller wrote:
> > > @@ -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);
> >
> > Hmm? These don't seem right. It also has a weird code sequence:
> ...
> > Did something go wrong there?
>
> Yes, I fixed those up after doing some allmodconfig builds.
>
> Here is the final patch I actually pushed to Linus:
That fixes up the sg_mark_end() bit, but it's still calling
sg_init_table() just a few lines further down. Is that correct?
--
Jens Axboe
^ permalink raw reply
* [PATCH 2.6.24 1/1]S2io: Support for add/delete/store/restore ethernet addresses
From: Sreenivasa Honnur @ 2007-10-31 8:08 UTC (permalink / raw)
To: netdev, jeff; +Cc: support
- Support to add/delete/store/restore 64 and 128 Ethernet addresses for Xframe I and Xframe II respectively.
Signed-off-by: Sreenivasa Honnur <sreenivasa.honnur@neterion.com>
---
diff -urpN org/drivers/net/s2io.c patch_1/drivers/net/s2io.c
--- org/drivers/net/s2io.c 2007-09-26 00:01:14.000000000 +0530
+++ patch_1/drivers/net/s2io.c 2007-09-26 22:42:11.000000000 +0530
@@ -84,7 +84,7 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "2.0.26.5"
+#define DRV_VERSION "2.0.26.6"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
@@ -3363,6 +3363,9 @@ static void s2io_reset(struct s2io_nic *
/* Set swapper to enable I/O register access */
s2io_set_swapper(sp);
+ /* restore mac address entries */
+ do_s2io_restore_unicast_mc(sp);
+
/* Restore the MSIX table entries from local variables */
restore_xmsi_data(sp);
@@ -3421,9 +3424,6 @@ static void s2io_reset(struct s2io_nic *
writeq(val64, &bar0->pcc_err_reg);
}
- /* restore the previously assigned mac address */
- do_s2io_prog_unicast(sp->dev, (u8 *)&sp->def_mac_addr[0].mac_addr);
-
sp->device_enabled_once = FALSE;
}
@@ -3896,8 +3896,17 @@ hw_init_failed:
static int s2io_close(struct net_device *dev)
{
struct s2io_nic *sp = dev->priv;
+ struct config_param *config = &sp->config;
+ u64 tmp64;
+ int off;
netif_stop_queue(dev);
+ /* delete all populated mac entries */
+ for (off = 1; off < config->max_mc_addr; off++) {
+ tmp64 = do_s2io_read_unicast_mc(sp, off);
+ if (tmp64 != S2IO_DISABLE_MAC_ENTRY)
+ do_s2io_delete_unicast_mc(sp, tmp64);
+ }
napi_disable(&sp->napi);
/* Reset card, kill tasklet and free Tx and Rx buffers. */
s2io_card_down(sp);
@@ -4699,8 +4708,9 @@ static void s2io_set_multicast(struct ne
struct XENA_dev_config __iomem *bar0 = sp->bar0;
u64 val64 = 0, multi_mac = 0x010203040506ULL, mask =
0xfeffffffffffULL;
- u64 dis_addr = 0xffffffffffffULL, mac_addr = 0;
+ u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, mac_addr = 0;
void __iomem *add;
+ struct config_param *config = &sp->config;
if ((dev->flags & IFF_ALLMULTI) && (!sp->m_cast_flg)) {
/* Enable all Multicast addresses */
@@ -4710,7 +4720,7 @@ static void s2io_set_multicast(struct ne
&bar0->rmac_addr_data1_mem);
val64 = RMAC_ADDR_CMD_MEM_WE |
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
- RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET);
+ RMAC_ADDR_CMD_MEM_OFFSET(config->max_mc_addr - 1);
writeq(val64, &bar0->rmac_addr_cmd_mem);
/* Wait till command completes */
wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
@@ -4718,7 +4728,7 @@ static void s2io_set_multicast(struct ne
S2IO_BIT_RESET);
sp->m_cast_flg = 1;
- sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET;
+ sp->all_multi_pos = config->max_mc_addr - 1;
} else if ((dev->flags & IFF_ALLMULTI) && (sp->m_cast_flg)) {
/* Disable all Multicast addresses */
writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
@@ -4787,7 +4797,7 @@ static void s2io_set_multicast(struct ne
/* Update individual M_CAST address list */
if ((!sp->m_cast_flg) && dev->mc_count) {
if (dev->mc_count >
- (MAX_ADDRS_SUPPORTED - MAC_MC_ADDR_START_OFFSET - 1)) {
+ (config->max_mc_addr - config->max_mac_addr)) {
DBG_PRINT(ERR_DBG, "%s: No more Rx filters ",
dev->name);
DBG_PRINT(ERR_DBG, "can be added, please enable ");
@@ -4807,7 +4817,7 @@ static void s2io_set_multicast(struct ne
val64 = RMAC_ADDR_CMD_MEM_WE |
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
RMAC_ADDR_CMD_MEM_OFFSET
- (MAC_MC_ADDR_START_OFFSET + i);
+ (config->mc_start_offset + i);
writeq(val64, &bar0->rmac_addr_cmd_mem);
/* Wait for command completes */
@@ -4839,7 +4849,7 @@ static void s2io_set_multicast(struct ne
val64 = RMAC_ADDR_CMD_MEM_WE |
RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
RMAC_ADDR_CMD_MEM_OFFSET
- (i + MAC_MC_ADDR_START_OFFSET);
+ (i + config->mc_start_offset);
writeq(val64, &bar0->rmac_addr_cmd_mem);
/* Wait for command completes */
@@ -4855,8 +4865,76 @@ static void s2io_set_multicast(struct ne
}
}
-/* add unicast MAC address to CAM */
-static int do_s2io_add_unicast(struct s2io_nic *sp, u64 addr, int off)
+/* read from CAM unicast & multicast addresses and store it in def_mac_addr structure
++ **/
+void do_s2io_store_unicast_mc(struct s2io_nic *sp)
+{
+ int offset;
+ u64 mac_addr = 0x0;
+ struct config_param *config = &sp->config;
+
+ /* store unicast & multicast mac addresses */
+ for (offset = 0; offset < config->max_mc_addr; offset++) {
+ mac_addr = do_s2io_read_unicast_mc(sp, offset);
+ /* if read fails disable the entry */
+ if (mac_addr == FAILURE)
+ mac_addr = S2IO_DISABLE_MAC_ENTRY;
+ do_s2io_copy_mac_addr(sp, offset, mac_addr);
+ }
+}
+
+/* restore unicast addresses & multicast to CAM from def_mac_addr structure */
+static void do_s2io_restore_unicast_mc(struct s2io_nic *sp)
+{
+ int offset;
+ struct config_param *config = &sp->config;
+
+ /* restore unicast mac address */
+ for (offset = 0; offset < config->max_mac_addr; offset++)
+ do_s2io_prog_unicast(sp->dev, sp->def_mac_addr[offset].mac_addr);
+
+ /* restore multicast mac address */
+ for (offset = config->mc_start_offset;
+ offset < config->max_mc_addr; offset++)
+ do_s2io_add_mc(sp, sp->def_mac_addr[offset].mac_addr);
+}
+
+/* add a multicast MAC address to CAM */
+static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr)
+{
+ int i;
+ u64 mac_addr = 0;
+ struct config_param *config = &sp->config;
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ mac_addr <<= 8;
+ mac_addr |= addr[i];
+ }
+ if ((0ULL == mac_addr) || (mac_addr == S2IO_DISABLE_MAC_ENTRY))
+ return SUCCESS;
+
+ /* check if the multicast mac already preset in CAM */
+ for (i = config->mc_start_offset; i < config->max_mc_addr; i++) {
+ u64 tmp64;
+ tmp64 = do_s2io_read_unicast_mc(sp, i);
+ if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */
+ break;
+
+ if (tmp64 == mac_addr)
+ return SUCCESS;
+ }
+ if (i == config->max_mc_addr) {
+ DBG_PRINT(ERR_DBG, "CAM full no space left for multicast MAC\n");
+ return FAILURE;
+ }
+ /* Update the internal structure with this new mac address */
+ do_s2io_copy_mac_addr(sp, i, mac_addr);
+
+ return (do_s2io_add_mac(sp, mac_addr, i));
+}
+
+/* add MAC address to CAM memory */
+static int do_s2io_add_mac(struct s2io_nic *sp, u64 addr, int off)
{
u64 val64;
struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -4879,6 +4957,53 @@ static int do_s2io_add_unicast(struct s2
return SUCCESS;
}
+/* deletes a specified unicast/multicast mac entry from CAM */
+static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr)
+{
+ int off;
+ u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, tmp64;
+ struct config_param *config = &sp->config;
+
+ for (off = 1;
+ off < config->max_mc_addr; off++) {
+ tmp64 = do_s2io_read_unicast_mc(sp, off);
+ if (tmp64 == addr) {
+ /* disable the entry by writing 0xffffffffffffULL */
+ if (do_s2io_add_mac(sp, dis_addr, off) == FAILURE)
+ return FAILURE;
+ /* store the new mac list from CAM */
+ do_s2io_store_unicast_mc(sp);
+ return SUCCESS;
+ }
+ }
+ DBG_PRINT(ERR_DBG, "MAC address 0x%llx not found in CAM\n",
+ (unsigned long long)addr);
+ return FAILURE;
+}
+
+/* read mac entries from CAM */
+static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset)
+{
+ u64 tmp64 = 0xffffffffffff0000ULL, val64;
+ struct XENA_dev_config __iomem *bar0 = sp->bar0;
+
+ /* read mac addr */
+ val64 =
+ RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
+ RMAC_ADDR_CMD_MEM_OFFSET(offset);
+ writeq(val64, &bar0->rmac_addr_cmd_mem);
+
+ /* Wait till command completes */
+ if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+ RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+ S2IO_BIT_RESET)) {
+ DBG_PRINT(INFO_DBG, "do_s2io_read_unicast_mc failed\n");
+ return FAILURE;
+ }
+ tmp64 = readq(&bar0->rmac_addr_data0_mem);
+ return (tmp64 >> 16);
+}
+
/**
* s2io_set_mac_addr driver entry point
*/
@@ -4909,6 +5034,8 @@ static int do_s2io_prog_unicast(struct n
struct s2io_nic *sp = dev->priv;
register u64 mac_addr = 0, perm_addr = 0;
int i;
+ u64 tmp64;
+ struct config_param *config = &sp->config;
/*
* Set the new MAC address as the new unicast filter and reflect this
@@ -4926,9 +5053,27 @@ static int do_s2io_prog_unicast(struct n
if (mac_addr == perm_addr)
return SUCCESS;
+ /* check if the mac already preset in CAM */
+ for (i = 1; i < config->max_mac_addr; i++) {
+ tmp64 = do_s2io_read_unicast_mc(sp, i);
+ if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */
+ break;
+
+ if (tmp64 == mac_addr) {
+ DBG_PRINT(INFO_DBG,
+ "MAC addr:0x%llx already present in CAM\n",
+ (unsigned long long)mac_addr);
+ return SUCCESS;
+ }
+ }
+ if (i == config->max_mac_addr) {
+ DBG_PRINT(ERR_DBG, "CAM full no space left for Unicast MAC\n");
+ return FAILURE;
+ }
+
/* Update the internal structure with this new mac address */
- do_s2io_copy_mac_addr(sp, 0, mac_addr);
- return (do_s2io_add_unicast(sp, mac_addr, 0));
+ do_s2io_copy_mac_addr(sp, i, mac_addr);
+ return (do_s2io_add_mac(sp, mac_addr, i));
}
/**
@@ -7625,7 +7770,7 @@ s2io_init_nic(struct pci_dev *pdev, cons
*/
bar0 = sp->bar0;
val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
- RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET);
+ RMAC_ADDR_CMD_MEM_OFFSET(0 + S2IO_MAC_ADDR_START_OFFSET);
writeq(val64, &bar0->rmac_addr_cmd_mem);
wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, S2IO_BIT_RESET);
@@ -7645,7 +7790,22 @@ s2io_init_nic(struct pci_dev *pdev, cons
memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
- /* Store the values of the MSIX table in the s2io_nic structure */
+ /* initialize number of multicast & unicast MAC entries variables */
+ if (sp->device_type == XFRAME_I_DEVICE) {
+ config->max_mc_addr = S2IO_XENA_MAX_MC_ADDRESSES;
+ config->max_mac_addr = S2IO_XENA_MAX_MAC_ADDRESSES;
+ config->mc_start_offset = S2IO_XENA_MC_ADDR_START_OFFSET;
+ }
+ else if (sp->device_type == XFRAME_II_DEVICE) {
+ config->max_mc_addr = S2IO_HERC_MAX_MC_ADDRESSES;
+ config->max_mac_addr = S2IO_HERC_MAX_MAC_ADDRESSES;
+ config->mc_start_offset = S2IO_HERC_MC_ADDR_START_OFFSET;
+ }
+
+ /* store mac addresses from CAM to s2io_nic structure */
+ do_s2io_store_unicast_mc(sp);
+
+ /* Store the values of the MSIX table in the s2io_nic structure */
store_xmsi_data(sp);
/* reset Nic and bring it to known state */
s2io_reset(sp);
diff -urpN org/drivers/net/s2io.h patch_1/drivers/net/s2io.h
--- org/drivers/net/s2io.h 2007-09-26 00:01:14.000000000 +0530
+++ patch_1/drivers/net/s2io.h 2007-09-26 02:34:11.000000000 +0530
@@ -31,6 +31,7 @@
#define SUCCESS 0
#define FAILURE -1
#define S2IO_MINUS_ONE 0xFFFFFFFFFFFFFFFFULL
+#define S2IO_DISABLE_MAC_ENTRY 0xFFFFFFFFFFFFULL
#define S2IO_MAX_PCI_CONFIG_SPACE_REINIT 100
#define S2IO_BIT_RESET 1
#define S2IO_BIT_SET 2
@@ -458,6 +459,9 @@ struct config_param {
#define MAX_MTU_JUMBO (MAX_PYLD_JUMBO+18)
#define MAX_MTU_JUMBO_VLAN (MAX_PYLD_JUMBO+22)
u16 bus_speed;
+ int max_mc_addr; /* xena=64 herc=256 */
+ int max_mac_addr; /* xena=16 herc=64 */
+ int mc_start_offset; /* xena=16 herc=64 */
};
/* Structure representing MAC Addrs */
@@ -824,9 +828,8 @@ struct s2io_nic {
void __iomem *bar0;
void __iomem *bar1;
#define MAX_MAC_SUPPORTED 16
-#define MAX_SUPPORTED_MULTICASTS MAX_MAC_SUPPORTED
- struct mac_addr def_mac_addr[MAX_MAC_SUPPORTED];
+ struct mac_addr def_mac_addr[256];
struct net_device_stats stats;
int high_dma_flag;
@@ -850,10 +853,9 @@ struct s2io_nic {
#define PROMISC 1
#define ALL_MULTI 2
-#define MAX_ADDRS_SUPPORTED 64
u16 usr_addr_count;
u16 mc_addr_count;
- struct usr_addr usr_addrs[MAX_ADDRS_SUPPORTED];
+ struct usr_addr usr_addrs[256];
u16 m_cast_flg;
u16 all_multi_pos;
@@ -1066,6 +1068,12 @@ static int s2io_add_isr(struct s2io_nic
static void s2io_rem_isr(struct s2io_nic * sp);
static void restore_xmsi_data(struct s2io_nic *nic);
+static void do_s2io_store_unicast_mc(struct s2io_nic *sp);
+static void do_s2io_restore_unicast_mc(struct s2io_nic *sp);
+static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset);
+static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr);
+static int do_s2io_add_mac(struct s2io_nic *sp, u64 addr, int offset);
+static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr);
static int
s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,
diff -urpN org/drivers/net/s2io-regs.h patch_1/drivers/net/s2io-regs.h
--- org/drivers/net/s2io-regs.h 2007-09-26 00:01:14.000000000 +0530
+++ patch_1/drivers/net/s2io-regs.h 2007-09-26 02:37:53.000000000 +0530
@@ -721,12 +721,16 @@ struct XENA_dev_config {
u64 rmac_cfg_key;
#define RMAC_CFG_KEY(val) vBIT(val,0,16)
+#define S2IO_MAC_ADDR_START_OFFSET 0
-#define MAX_MAC_ADDRESSES 16
-#define MAX_MC_ADDRESSES 32 /* Multicast addresses */
-#define MAC_MAC_ADDR_START_OFFSET 0
-#define MAC_MC_ADDR_START_OFFSET 16
-#define MAC_MC_ALL_MC_ADDR_OFFSET 63 /* enables all multicast pkts */
+#define S2IO_XENA_MAX_MC_ADDRESSES 64 /* multicast addresses */
+#define S2IO_HERC_MAX_MC_ADDRESSES 256
+
+#define S2IO_XENA_MAX_MAC_ADDRESSES 16
+#define S2IO_HERC_MAX_MAC_ADDRESSES 64
+
+#define S2IO_XENA_MC_ADDR_START_OFFSET 16
+#define S2IO_HERC_MC_ADDR_START_OFFSET 64
u64 rmac_addr_cmd_mem;
#define RMAC_ADDR_CMD_MEM_WE BIT(7)
#define RMAC_ADDR_CMD_MEM_RD 0
^ permalink raw reply
* Re: [PATCH]: Fix networking scatterlist regressions.
From: David Miller @ 2007-10-31 8:08 UTC (permalink / raw)
To: jens.axboe; +Cc: netdev, herbert, rusty
In-Reply-To: <20071031080143.GD5059@kernel.dk>
From: Jens Axboe <jens.axboe@oracle.com>
Date: Wed, 31 Oct 2007 09:01:43 +0100
> On Wed, Oct 31 2007, David Miller wrote:
> > From: Jens Axboe <jens.axboe@oracle.com>
> > Date: Wed, 31 Oct 2007 08:46:21 +0100
> >
> > > On Tue, Oct 30 2007, David Miller wrote:
> > > > @@ -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);
> > >
> > > Hmm? These don't seem right. It also has a weird code sequence:
> > ...
> > > Did something go wrong there?
> >
> > Yes, I fixed those up after doing some allmodconfig builds.
> >
> > Here is the final patch I actually pushed to Linus:
>
> That fixes up the sg_mark_end() bit, but it's still calling
> sg_init_table() just a few lines further down. Is that correct?
Absolutely. It initially using the scatterlist for this
crypto layer call:
ret = crypto_blkcipher_decrypt_iv(&desc->desc, desc->frags,
desc->frags, thislen);
if (ret)
return ret;
then it reinits and sets the sglist to the values the caller
wants.
^ permalink raw reply
* [PATCH 2.6.24 1/1]S2io: Fixed memory leak by freeing MSI-X local entry memories when vector allocation fails
From: Sreenivasa Honnur @ 2007-10-31 8:10 UTC (permalink / raw)
To: netdev, jeff; +Cc: support
- Fixed memory leak by freeing MSI-X local entry memories when vector allocation
fails in s2io_add_isr.
- Added two utility functions remove_msix_isr and remove_inta_isr to eliminate
code duplication.
- Implemented following review comments from Jeff
- Removed redundant stats->mem_freed and synchronize_irq call
- do_rem_msix_isr is renamed as remove_msix_isr
- do_rem_inta_isr is renamed as remove_inta_isr
Signed-off-by: Sreenivasa Honnur <sreenivasa.honnur@neterion.com>
Signed-off-by: Ramkrishna Vepa <ram.vepa@neterion.com>
---
diff -Nurp org/drivers/net/s2io.c patch1/drivers/net/s2io.c
--- org/drivers/net/s2io.c 2007-10-30 23:31:09.000000000 +0530
+++ patch1/drivers/net/s2io.c 2007-10-31 04:12:00.000000000 +0530
@@ -84,7 +84,7 @@
#include "s2io.h"
#include "s2io-regs.h"
-#define DRV_VERSION "2.0.26.6"
+#define DRV_VERSION "2.0.26.7"
/* S2io Driver name & version. */
static char s2io_driver_name[] = "Neterion";
@@ -3775,6 +3775,40 @@ static int __devinit s2io_test_msi(struc
return err;
}
+
+static void remove_msix_isr(struct s2io_nic *sp)
+{
+ int i;
+ u16 msi_control;
+
+ for (i = 0; i < MAX_REQUESTED_MSI_X; i++) {
+ if (sp->s2io_entries[i].in_use ==
+ MSIX_REGISTERED_SUCCESS) {
+ int vector = sp->entries[i].vector;
+ void *arg = sp->s2io_entries[i].arg;
+ free_irq(vector, arg);
+ }
+ }
+
+ kfree(sp->entries);
+ kfree(sp->s2io_entries);
+ sp->entries = NULL;
+ sp->s2io_entries = NULL;
+
+ pci_read_config_word(sp->pdev, 0x42, &msi_control);
+ msi_control &= 0xFFFE; /* Disable MSI */
+ pci_write_config_word(sp->pdev, 0x42, msi_control);
+
+ pci_disable_msix(sp->pdev);
+}
+
+static void remove_inta_isr(struct s2io_nic *sp)
+{
+ struct net_device *dev = sp->dev;
+
+ free_irq(sp->pdev->irq, dev);
+}
+
/* ********************************************************* *
* Functions defined below concern the OS part of the driver *
* ********************************************************* */
@@ -3809,28 +3843,9 @@ static int s2io_open(struct net_device *
int ret = s2io_enable_msi_x(sp);
if (!ret) {
- u16 msi_control;
-
ret = s2io_test_msi(sp);
-
/* rollback MSI-X, will re-enable during add_isr() */
- kfree(sp->entries);
- sp->mac_control.stats_info->sw_stat.mem_freed +=
- (MAX_REQUESTED_MSI_X *
- sizeof(struct msix_entry));
- kfree(sp->s2io_entries);
- sp->mac_control.stats_info->sw_stat.mem_freed +=
- (MAX_REQUESTED_MSI_X *
- sizeof(struct s2io_msix_entry));
- sp->entries = NULL;
- sp->s2io_entries = NULL;
-
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
-
- pci_disable_msix(sp->pdev);
-
+ remove_msix_isr(sp);
}
if (ret) {
@@ -6864,15 +6879,23 @@ static int s2io_add_isr(struct s2io_nic
}
}
if (err) {
+ remove_msix_isr(sp);
+
DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
"failed\n", dev->name, i);
- DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
- return -1;
+ DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n",
+ dev->name);
+ sp->config.intr_type = INTA;
+ break;
}
sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
}
- printk("MSI-X-TX %d entries enabled\n",msix_tx_cnt);
- printk("MSI-X-RX %d entries enabled\n",msix_rx_cnt);
+ if (!err) {
+ DBG_PRINT(INFO_DBG, "MSI-X-TX %d entries enabled\n",
+ msix_tx_cnt);
+ DBG_PRINT(INFO_DBG, "MSI-X-RX %d entries enabled\n",
+ msix_rx_cnt);
+ }
}
if (sp->config.intr_type == INTA) {
err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
@@ -6887,40 +6910,10 @@ static int s2io_add_isr(struct s2io_nic
}
static void s2io_rem_isr(struct s2io_nic * sp)
{
- struct net_device *dev = sp->dev;
- struct swStat *stats = &sp->mac_control.stats_info->sw_stat;
-
- if (sp->config.intr_type == MSI_X) {
- int i;
- u16 msi_control;
-
- for (i=1; (sp->s2io_entries[i].in_use ==
- MSIX_REGISTERED_SUCCESS); i++) {
- int vector = sp->entries[i].vector;
- void *arg = sp->s2io_entries[i].arg;
-
- synchronize_irq(vector);
- free_irq(vector, arg);
- }
-
- kfree(sp->entries);
- stats->mem_freed +=
- (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
- kfree(sp->s2io_entries);
- stats->mem_freed +=
- (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
- sp->entries = NULL;
- sp->s2io_entries = NULL;
-
- pci_read_config_word(sp->pdev, 0x42, &msi_control);
- msi_control &= 0xFFFE; /* Disable MSI */
- pci_write_config_word(sp->pdev, 0x42, msi_control);
-
- pci_disable_msix(sp->pdev);
- } else {
- synchronize_irq(sp->pdev->irq);
- free_irq(sp->pdev->irq, dev);
- }
+ if (sp->config.intr_type == MSI_X)
+ remove_msix_isr(sp);
+ else
+ remove_inta_isr(sp);
}
static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
^ permalink raw reply
* Re: [PATCH]: Fix networking scatterlist regressions.
From: Jens Axboe @ 2007-10-31 8:08 UTC (permalink / raw)
To: David Miller; +Cc: netdev, herbert, rusty
In-Reply-To: <20071031.010842.13648022.davem@davemloft.net>
On Wed, Oct 31 2007, David Miller wrote:
> From: Jens Axboe <jens.axboe@oracle.com>
> Date: Wed, 31 Oct 2007 09:01:43 +0100
>
> > On Wed, Oct 31 2007, David Miller wrote:
> > > From: Jens Axboe <jens.axboe@oracle.com>
> > > Date: Wed, 31 Oct 2007 08:46:21 +0100
> > >
> > > > On Tue, Oct 30 2007, David Miller wrote:
> > > > > @@ -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);
> > > >
> > > > Hmm? These don't seem right. It also has a weird code sequence:
> > > ...
> > > > Did something go wrong there?
> > >
> > > Yes, I fixed those up after doing some allmodconfig builds.
> > >
> > > Here is the final patch I actually pushed to Linus:
> >
> > That fixes up the sg_mark_end() bit, but it's still calling
> > sg_init_table() just a few lines further down. Is that correct?
>
> Absolutely. It initially using the scatterlist for this
> crypto layer call:
>
> ret = crypto_blkcipher_decrypt_iv(&desc->desc, desc->frags,
> desc->frags, thislen);
> if (ret)
> return ret;
>
> then it reinits and sets the sglist to the values the caller
> wants.
Great, just wanted to double check that it was indeed correct!
--
Jens Axboe
^ permalink raw reply
* Re: [PATCH]: Fix networking scatterlist regressions.
From: Jens Axboe @ 2007-10-31 8:14 UTC (permalink / raw)
To: David Miller; +Cc: netdev, herbert, rusty
In-Reply-To: <20071031.005802.204286555.davem@davemloft.net>
On Wed, Oct 31 2007, David Miller wrote:
> From: Jens Axboe <jens.axboe@oracle.com>
> Date: Wed, 31 Oct 2007 08:46:21 +0100
>
> > On Tue, Oct 30 2007, David Miller wrote:
> > > @@ -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);
> >
> > Hmm? These don't seem right. It also has a weird code sequence:
> ...
> > Did something go wrong there?
>
> Yes, I fixed those up after doing some allmodconfig builds.
>
> Here is the final patch I actually pushed to Linus:
Here's the sg_mark_end() patch on top of that.
>From 2f5371509d3d4d09269bf7a46868da2ac5c61d77 Mon Sep 17 00:00:00 2001
From: Jens Axboe <jens.axboe@oracle.com>
Date: Wed, 31 Oct 2007 09:11:10 +0100
Subject: [PATCH] [SG] Get rid of __sg_mark_end()
sg_mark_end() overwrites the page_link information, but all users want
__sg_mark_end() behaviour where we just set the end bit. That is the most
natural way to use the sg list, since you'll fill it in and then mark the
end point.
So change sg_mark_end() to only set the termination bit. Add a sg_magic
debug check as well, and clear a chain pointer if it is set.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
---
block/ll_rw_blk.c | 2 +-
drivers/scsi/scsi_lib.c | 2 +-
include/linux/scatterlist.h | 22 ++++++++++++----------
net/core/skbuff.c | 2 +-
net/ipv4/tcp_ipv4.c | 2 +-
net/ipv6/tcp_ipv6.c | 2 +-
net/rxrpc/rxkad.c | 2 +-
net/sunrpc/auth_gss/gss_krb5_crypto.c | 6 +++---
8 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index e948407..fdc0707 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -1369,7 +1369,7 @@ new_segment:
} /* segments in rq */
if (sg)
- __sg_mark_end(sg);
+ sg_mark_end(sg);
return nsegs;
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 61fdaf0..88de771 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -785,7 +785,7 @@ struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask)
* end-of-list
*/
if (!left)
- sg_mark_end(sgl, this);
+ sg_mark_end(&sgl[this - 1]);
/*
* don't allow subsequent mempool allocs to sleep, it would
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index d5e1876..b2116a1 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -188,21 +188,23 @@ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents,
/**
* sg_mark_end - Mark the end of the scatterlist
- * @sgl: Scatterlist
- * @nents: Number of entries in sgl
+ * @sg: SG entryScatterlist
*
* Description:
- * Marks the last entry as the termination point for sg_next()
+ * Marks the passed in sg entry as the termination point for the sg
+ * table. A call to sg_next() on this entry will return NULL.
*
**/
-static inline void sg_mark_end(struct scatterlist *sgl, unsigned int nents)
-{
- sgl[nents - 1].page_link = 0x02;
-}
-
-static inline void __sg_mark_end(struct scatterlist *sg)
+static inline void sg_mark_end(struct scatterlist *sg)
{
+#ifdef CONFIG_DEBUG_SG
+ BUG_ON(sg->sg_magic != SG_MAGIC);
+#endif
+ /*
+ * Set termination bit, clear potential chain bit
+ */
sg->page_link |= 0x02;
+ sg->page_link &= ~0x01;
}
/**
@@ -218,7 +220,7 @@ static inline void __sg_mark_end(struct scatterlist *sg)
static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
{
memset(sgl, 0, sizeof(*sgl) * nents);
- sg_mark_end(sgl, nents);
+ sg_mark_end(&sgl[nents - 1]);
#ifdef CONFIG_DEBUG_SG
{
unsigned int i;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 64b50ff..32d5826 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2095,7 +2095,7 @@ int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int le
{
int nsg = __skb_to_sgvec(skb, sg, offset, len);
- __sg_mark_end(&sg[nsg - 1]);
+ sg_mark_end(&sg[nsg - 1]);
return nsg;
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index eec02b2..d438dfb 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 - 1]);
+ sg_mark_end(&sg[block - 1]);
/* Now store the Hash into the packet */
err = crypto_hash_init(desc);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 4b90328..06be2a1 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 - 1]);
+ 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 c387cf6..e09a95a 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -702,7 +702,7 @@ static void rxkad_sg_set_buf2(struct scatterlist sg[2],
nsg++;
}
- __sg_mark_end(&sg[nsg - 1]);
+ sg_mark_end(&sg[nsg - 1]);
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 ab7cbd6..0dd7923 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 - 1]);
- __sg_mark_end(&desc->outfrags[desc->fragno - 1]);
+ sg_mark_end(&desc->infrags[desc->fragno - 1]);
+ sg_mark_end(&desc->outfrags[desc->fragno - 1]);
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 - 1]);
+ sg_mark_end(&desc->frags[desc->fragno - 1]);
ret = crypto_blkcipher_decrypt_iv(&desc->desc, desc->frags,
desc->frags, thislen);
--
1.5.3.GIT
--
Jens Axboe
^ permalink raw reply related
* [PATCH v3] using mii-bitbang on different processor ports
From: Sergej Stepanov @ 2007-10-31 8:32 UTC (permalink / raw)
To: linuxppc-dev, netdev, jgarzik
The patch makes possible to have mdio and mdc pins on different physical ports
also for CONFIG_PPC_CPM_NEW_BINDING.
To setup it in the device tree:
reg = <10d40 14 10d60 14>; // mdc: 0x10d40, mdio: 0x10d60
or
reg = <10d40 14>; // mdc and mdio have the same offset 10d40
The approach was taken from older version.
Signed-off-by: Sergej Stepanov <Sergej.Stepanov@ids.de>
--
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index b8e4a73..83ce0c6 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -29,12 +29,16 @@
#include "fs_enet.h"
-struct bb_info {
- struct mdiobb_ctrl ctrl;
+struct bb_port {
__be32 __iomem *dir;
__be32 __iomem *dat;
- u32 mdio_msk;
- u32 mdc_msk;
+ u32 msk;
+};
+
+struct bb_info {
+ struct mdiobb_ctrl ctrl;
+ struct bb_port mdc;
+ struct bb_port mdio;
};
/* FIXME: If any other users of GPIO crop up, then these will have to
@@ -62,18 +66,18 @@ static inline void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
if (dir)
- bb_set(bitbang->dir, bitbang->mdio_msk);
+ bb_set(bitbang->mdio.dir, bitbang->mdio.msk);
else
- bb_clr(bitbang->dir, bitbang->mdio_msk);
+ bb_clr(bitbang->mdio.dir, bitbang->mdio.msk);
/* Read back to flush the write. */
- in_be32(bitbang->dir);
+ in_be32(bitbang->mdio.dir);
}
static inline int mdio_read(struct mdiobb_ctrl *ctrl)
{
struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
- return bb_read(bitbang->dat, bitbang->mdio_msk);
+ return bb_read(bitbang->mdio.dat, bitbang->mdio.msk);
}
static inline void mdio(struct mdiobb_ctrl *ctrl, int what)
@@ -81,12 +85,12 @@ static inline void mdio(struct mdiobb_ctrl *ctrl, int what)
struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
if (what)
- bb_set(bitbang->dat, bitbang->mdio_msk);
+ bb_set(bitbang->mdio.dat, bitbang->mdio.msk);
else
- bb_clr(bitbang->dat, bitbang->mdio_msk);
+ bb_clr(bitbang->mdio.dat, bitbang->mdio.msk);
/* Read back to flush the write. */
- in_be32(bitbang->dat);
+ in_be32(bitbang->mdio.dat);
}
static inline void mdc(struct mdiobb_ctrl *ctrl, int what)
@@ -94,12 +98,12 @@ static inline void mdc(struct mdiobb_ctrl *ctrl, int what)
struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
if (what)
- bb_set(bitbang->dat, bitbang->mdc_msk);
+ bb_set(bitbang->mdc.dat, bitbang->mdc.msk);
else
- bb_clr(bitbang->dat, bitbang->mdc_msk);
+ bb_clr(bitbang->mdc.dat, bitbang->mdc.msk);
/* Read back to flush the write. */
- in_be32(bitbang->dat);
+ in_be32(bitbang->mdc.dat);
}
static struct mdiobb_ops bb_ops = {
@@ -142,15 +146,32 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
return -ENODEV;
mdc_pin = *data;
- bitbang->dir = ioremap(res.start, res.end - res.start + 1);
- if (!bitbang->dir)
+ bitbang->mdc.dir = ioremap(res.start, res.end - res.start + 1);
+ if (!bitbang->mdc.dir)
return -ENOMEM;
- bitbang->dat = bitbang->dir + 4;
- bitbang->mdio_msk = 1 << (31 - mdio_pin);
- bitbang->mdc_msk = 1 << (31 - mdc_pin);
+ bitbang->mdc.dat = bitbang->mdc.dir + 4;
+ if (!of_address_to_resource(np, 1, &res)) {
+ if (res.end - res.start < 13)
+ goto bad_resource;
+ bitbang->mdio.dir = ioremap(res.start, res.end - res.start + 1);
+ if (!bitbang->mdio.dir)
+ goto unmap_and_exit;
+ bitbang->mdio.dat = bitbang->mdio.dir + 4;
+ } else {
+ bitbang->mdio.dir = bitbang->mdc.dir;
+ bitbang->mdio.dat = bitbang->mdc.dat;
+ }
+ bitbang->mdio.msk = 1 << (31 - mdio_pin);
+ bitbang->mdc.msk = 1 << (31 - mdc_pin);
return 0;
+bad_resource:
+ iounmap(bitbang->mdc.dir);
+ return -ENODEV;
+unmap_and_exit:
+ iounmap(bitbang->mdc.dir);
+ return -ENOMEM;
}
static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
@@ -220,7 +241,9 @@ out_free_irqs:
dev_set_drvdata(&ofdev->dev, NULL);
kfree(new_bus->irq);
out_unmap_regs:
- iounmap(bitbang->dir);
+ if (bitbang->mdio.dir != bitbang->mdc.dir)
+ iounmap(bitbang->mdio.dir);
+ iounmap(bitbang->mdc.dir);
out_free_bus:
kfree(new_bus);
out_free_priv:
@@ -238,6 +261,8 @@ static int fs_enet_mdio_remove(struct of_device *ofdev)
free_mdio_bitbang(bus);
dev_set_drvdata(&ofdev->dev, NULL);
kfree(bus->irq);
- iounmap(bitbang->dir);
+ if (bitbang->mdio.dir != bitbang->mdc.dir)
+ iounmap(bitbang->mdio.dir);
+ iounmap(bitbang->mdc.dir);
kfree(bitbang);
kfree(bus);
^ permalink raw reply related
* Re: Oops in 2.6.21-rc4, 2.6.23
From: Jarek Poplawski @ 2007-10-31 8:39 UTC (permalink / raw)
To: David Miller; +Cc: darko.koruga, netdev
In-Reply-To: <20071030141120.GA3997@ff.dom.local>
On Tue, Oct 30, 2007 at 03:11:20PM +0100, Jarek Poplawski wrote:
> On Mon, Oct 29, 2007 at 01:41:47AM -0700, David Miller wrote:
> ...
> > Actually, this was caused by a real bug in the SKB_WITH_OVERHEAD macro
> > definition, which Herbert Xu quickly spotted and fixed.
> >
> > Which "I hope you've found this by yourself by now".
> >
>
> ...Btw, of course you have to be right, and I should find this in max.
> 12 days yet, if I'm as smart as I hope. But as for now, I really can't
> see any meaningful difference between this "buggy" SKB_WITH_OVERHEAD
> version and 'generic' 2.6.20.
OK. At last I've found "by myself", what you seemed to suggest with
such a great subtlety... So, there was this another, bugzilla thread...
And, accidentally of course, I could have been not so 100% wrong, as
expected?!
Regards,
Jarek P.
^ permalink raw reply
* Re: [PATCH 00/33] Swap over NFS -v14
From: Christoph Hellwig @ 2007-10-31 8:50 UTC (permalink / raw)
To: David Miller
Cc: nickpiggin, a.p.zijlstra, torvalds, akpm, linux-kernel, linux-mm,
netdev, trond.myklebust
In-Reply-To: <20071030.213753.126064697.davem@davemloft.net>
On Tue, Oct 30, 2007 at 09:37:53PM -0700, David Miller wrote:
> 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.
So can we please do swap over network storage only first? All these
VM bits look conceptually sane to me, while the changes to the swap
code to support nfs are real crackpipe material. Then again doing
that part properly by adding address_space methods for swap I/O without
the abuse might be a really good idea, especially as the way we
do swapfiles on block-based filesystems is an horrible hack already.
So please get the VM bits for swap over network blockdevices in first,
and then we can look into a complete revamp of the swapfile support
that cleans up the current mess and adds support for nfs insted of
making the mess even worse.
^ permalink raw reply
* Re: [PATCH 28/33] nfs: teach the NFS client how to treat PG_swapcache pages
From: Christoph Hellwig @ 2007-10-31 8:52 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Linus Torvalds, Andrew Morton, linux-kernel, linux-mm, netdev,
trond.myklebust
In-Reply-To: <20071030160915.377778000@chello.nl>
On Tue, Oct 30, 2007 at 05:04:29PM +0100, Peter Zijlstra wrote:
> Replace all relevant occurences of page->index and page->mapping in the NFS
> client with the new page_file_index() and page_file_mapping() functions.
As discussed personally and on the list a strong NACK for this. Swapcache
pages have no business at all ever coming through ->writepage(s). If you
really want to support swap over NFS that can only be done properly by
adding separate methods to write out and read in pages separated from the
pagecache. Incidentally that would also clean up the mess we have with
swap files on "normal" filesystems using ->bmap and bypassing the filesystem
later on.
^ permalink raw reply
* Re: [PATCH][RFC] Add support for the RDC R6040 Fast Ethernet controller
From: Jeff Garzik @ 2007-10-31 8:57 UTC (permalink / raw)
To: Florian Fainelli; +Cc: netdev
In-Reply-To: <200710292251.43257.florian.fainelli@telecomint.eu>
Florian Fainelli wrote:
> This patch adds support for the RDC R6040 MAC we can find in the RDC R-321x System-on-chips.
> This driver really needs improvements especially on the NAPI part which probably does not
> fully use the new NAPI structure.
> You will need the RDC PCI identifiers if you want to test this driver which are the following ones :
>
> RDC_PCI_VENDOR_ID = 0x17f3
> RDC_PCI_DEVICE_ID_RDC_R6040 = 0x6040
>
> Thank you very much in advance for your comments.
>
> Signed-off-by: Sten Wang <sten.wang@rdc.com.tw>
> Signed-off-by: Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
> Signed-off-by: Florian Fainelli <florian.fainelli@telecomint.eu>
Looks nice and clean to me. Pre-merge stuff I think needs fixing:
* clean up NAPI as you describe (and delete non-NAPI code paths, unless
there is a strong reason to keep them).
* unconditional local_irq_{enable,disable} stuff
* spin_lock_irqsave() should not be needed in interrupt handler.
[perhaps you did this rather than put the slower locking in
->poll_controller()]
* remove changelog from C header (git repository log is our changelog)
* handle large dev->mc_count, as you note in the C header
* use __le32 and similar data types. validate with sparse
(Documentation/sparse.txt)
* consider using ioread{8,16,32} and iowrite{8,16,32}, if your platform
permits. Then switch from 'unsigned long' to special marker 'void
__iomem *' for all I/O port addresses
* use DMA_32BIT_MASK rather than 0xffffffff in pci_set_dma_mask() call
* in r6040_init_one() call is_valid_ether_addr(), rather than
hand-rolling the same code yourself
* you need to note carrier state when it changes, using
netif_carrier_on() and netif_carrier_off()
^ permalink raw reply
* Re: [PATCH 2/2] NFS: handle IPv6 addresses in nfs ctl
From: Aurélien Charbon @ 2007-10-31 9:06 UTC (permalink / raw)
To: Brian Haley; +Cc: netdev ML, Mailing list NFSv4
In-Reply-To: <47278145.8010002@hp.com>
[-- Attachment #1: Type: text/plain, Size: 15624 bytes --]
Thank you Brian
Sorry, I did not see what you sent.
I have tested it with an IPv4 configuration. It's OK.
So Neil, Bruce, you can take this one for review.
fs/nfsd/export.c | 9 ++-
fs/nfsd/nfsctl.c | 42 ++++++++++++--
include/linux/sunrpc/svcauth.h | 5 +
include/net/ipv6.h | 10 +++
net/sunrpc/svcauth_unix.c | 118
+++++++++++++++++++++++++++--------------
5 files changed, 134 insertions(+), 50 deletions(-)
Signed-off-by: Brian Haley <brian.haley@hp.com>
Signed-off-by: Aurelien Charbon <aurelien.charbon@bull.net>
---
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 66d0aeb..c47ba77 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -35,6 +35,7 @@
#include <linux/lockd/bind.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/gss_api.h>
+#include <net/ipv6.h>
#define NFSDDBG_FACILITY NFSDDBG_EXPORT
@@ -1556,6 +1557,7 @@ exp_addclient(struct nfsctl_client *ncp)
{
struct auth_domain *dom;
int i, err;
+ struct in6_addr in6;
/* First, consistency check. */
err = -EINVAL;
@@ -1574,9 +1576,10 @@ exp_addclient(struct nfsctl_client *ncp)
goto out_unlock;
/* Insert client into hashtable. */
- for (i = 0; i < ncp->cl_naddr; i++)
- auth_unix_add_addr(ncp->cl_addrlist[i], dom);
-
+ for (i = 0; i < ncp->cl_naddr; i++) {
+ ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &in6);
+ auth_unix_add_addr(&in6, dom);
+ }
auth_unix_forget_old(dom);
auth_domain_put(dom);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 77dc989..5cb5f0d 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -37,6 +37,7 @@
#include <linux/nfsd/syscall.h>
#include <asm/uaccess.h>
+#include <net/ipv6.h>
/*
* We have a single directory with 9 nodes in it.
@@ -219,24 +220,37 @@ static ssize_t write_getfs(struct file *file, char
*buf, size_t size)
{
struct nfsctl_fsparm *data;
struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
struct auth_domain *clp;
int err = 0;
struct knfsd_fh *res;
+ struct in6_addr in6;
if (size < sizeof(*data))
return -EINVAL;
data = (struct nfsctl_fsparm*)buf;
err = -EPROTONOSUPPORT;
- if (data->gd_addr.sa_family != AF_INET)
+ switch (data->gd_addr.sa_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)&data->gd_addr;
+ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&data->gd_addr;
+ ipv6_addr_copy(&in6, &sin6->sin6_addr);
+ break;
+ default:
goto out;
- sin = (struct sockaddr_in *)&data->gd_addr;
+ }
+
if (data->gd_maxlen > NFS3_FHSIZE)
data->gd_maxlen = NFS3_FHSIZE;
res = (struct knfsd_fh*)buf;
exp_readlock();
- if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+ if (!(clp = auth_unix_lookup(&in6)))
err = -EPERM;
else {
err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
@@ -253,25 +267,41 @@ static ssize_t write_getfd(struct file *file, char
*buf, size_t size)
{
struct nfsctl_fdparm *data;
struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
struct auth_domain *clp;
int err = 0;
struct knfsd_fh fh;
char *res;
+ struct in6_addr in6;
if (size < sizeof(*data))
return -EINVAL;
data = (struct nfsctl_fdparm*)buf;
err = -EPROTONOSUPPORT;
- if (data->gd_addr.sa_family != AF_INET)
+ if (data->gd_addr.sa_family != AF_INET &&
+ data->gd_addr.sa_family != AF_INET6)
goto out;
err = -EINVAL;
if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
goto out;
res = buf;
- sin = (struct sockaddr_in *)&data->gd_addr;
exp_readlock();
- if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+ switch (data->gd_addr.sa_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)&data->gd_addr;
+ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&data->gd_addr;
+ ipv6_addr_copy(&in6, &sin6->sin6_addr);
+ break;
+ default:
+ goto out;
+ }
+
+ if (!(clp = auth_unix_lookup(&in6)))
err = -EPERM;
else {
err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index 22e1ef8..64ecb93 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -15,6 +15,7 @@
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/cache.h>
#include <linux/hash.h>
+#include <net/ipv6.h>
#define SVC_CRED_NGROUPS 32
struct svc_cred {
@@ -120,10 +121,10 @@ extern void
svc_auth_unregister(rpc_authflavor_t flavor);
extern struct auth_domain *unix_domain_find(char *name);
extern void auth_domain_put(struct auth_domain *item);
-extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain
*dom);
+extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain
*dom);
extern struct auth_domain *auth_domain_lookup(char *name, struct
auth_domain *new);
extern struct auth_domain *auth_domain_find(char *name);
-extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
+extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
extern int auth_unix_forget_old(struct auth_domain *dom);
extern void svcauth_unix_purge(void);
extern void svcauth_unix_info_release(void *);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index ae328b6..366fdca 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -16,6 +16,7 @@
#define _NET_IPV6_H
#include <linux/ipv6.h>
+#include <linux/in.h>
#include <linux/hardirq.h>
#include <net/if_inet6.h>
#include <net/ndisc.h>
@@ -400,6 +401,15 @@ static inline int ipv6_addr_v4mapped(const struct
in6_addr *a)
a->s6_addr32[2] == htonl(0x0000ffff));
}
+static inline void ipv6_addr_set_v4mapped(const __be32 addr,
+ struct in6_addr *v4mapped)
+{
+ ipv6_addr_set(v4mapped,
+ 0, 0,
+ __constant_htonl(0x0000FFFF),
+ addr);
+}
+
/*
* find the first different bit between two addresses
* length of address must be a multiple of 32bits
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 4114794..a40d769 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -11,6 +11,7 @@
#include <linux/hash.h>
#include <linux/string.h>
#include <net/sock.h>
+#include <net/ipv6.h>
#define RPCDBG_FACILITY RPCDBG_AUTH
@@ -84,7 +85,7 @@ static void svcauth_unix_domain_release(struct
auth_domain *dom)
struct ip_map {
struct cache_head h;
char m_class[8]; /* e.g. "nfsd" */
- struct in_addr m_addr;
+ struct in6_addr m_addr;
struct unix_domain *m_client;
int m_add_change;
};
@@ -101,7 +102,6 @@ static void ip_map_put(struct kref *kref)
kfree(im);
}
-#if IP_HASHBITS == 8
/* hash_long on a 64 bit machine is currently REALLY BAD for
* IP addresses in reverse-endian (i.e. on a little-endian machine).
* So use a trivial but reliable hash instead
@@ -111,13 +111,20 @@ static inline int hash_ip(__be32 ip)
int hash = (__force u32)ip ^ ((__force u32)ip>>16);
return (hash ^ (hash>>8)) & 0xff;
}
-#endif
+
+static inline int hash_ip6(struct in6_addr *ip6)
+{
+ return (hash_ip(ip6->s6_addr32[0]) ^
+ hash_ip(ip6->s6_addr32[1]) ^
+ hash_ip(ip6->s6_addr32[2]) ^
+ hash_ip(ip6->s6_addr32[3]));
+}
static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
{
struct ip_map *orig = container_of(corig, struct ip_map, h);
struct ip_map *new = container_of(cnew, struct ip_map, h);
return strcmp(orig->m_class, new->m_class) == 0
- && orig->m_addr.s_addr == new->m_addr.s_addr;
+ && ipv6_addr_equal(&orig->m_addr, &new->m_addr);
}
static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
{
@@ -125,7 +132,7 @@ static void ip_map_init(struct cache_head *cnew,
struct cache_head *citem)
struct ip_map *item = container_of(citem, struct ip_map, h);
strcpy(new->m_class, item->m_class);
- new->m_addr.s_addr = item->m_addr.s_addr;
+ ipv6_addr_copy(&new->m_addr, &item->m_addr);
}
static void update(struct cache_head *cnew, struct cache_head *citem)
{
@@ -149,22 +156,24 @@ static void ip_map_request(struct cache_detail *cd,
struct cache_head *h,
char **bpp, int *blen)
{
- char text_addr[20];
+ char text_addr[40];
struct ip_map *im = container_of(h, struct ip_map, h);
- __be32 addr = im->m_addr.s_addr;
-
- snprintf(text_addr, 20, "%u.%u.%u.%u",
- ntohl(addr) >> 24 & 0xff,
- ntohl(addr) >> 16 & 0xff,
- ntohl(addr) >> 8 & 0xff,
- ntohl(addr) >> 0 & 0xff);
+ if (ipv6_addr_v4mapped(&(im->m_addr))) {
+ snprintf(text_addr, 20, NIPQUAD_FMT,
+ ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
+ ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
+ ntohl(im->m_addr.s6_addr32[3]) >> 8 & 0xff,
+ ntohl(im->m_addr.s6_addr32[3]) >> 0 & 0xff);
+ } else {
+ snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
+ }
qword_add(bpp, blen, im->m_class);
qword_add(bpp, blen, text_addr);
(*bpp)[-1] = '\n';
}
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom,
time_t expiry);
static int ip_map_parse(struct cache_detail *cd,
@@ -175,10 +184,10 @@ static int ip_map_parse(struct cache_detail *cd,
* for scratch: */
char *buf = mesg;
int len;
- int b1,b2,b3,b4;
+ int b1, b2, b3, b4, b5, b6, b7, b8;
char c;
char class[8];
- struct in_addr addr;
+ struct in6_addr addr6;
int err;
struct ip_map *ipmp;
@@ -197,7 +206,23 @@ static int ip_map_parse(struct cache_detail *cd,
len = qword_get(&mesg, buf, mlen);
if (len <= 0) return -EINVAL;
- if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
+ if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
+ addr6.s6_addr32[0] = 0;
+ addr6.s6_addr32[1] = 0;
+ addr6.s6_addr32[2] = htonl(0xffff);
+ addr6.s6_addr32[3] =
+ htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+ } else if (sscanf(buf, NIP6_FMT "%c",
+ &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
+ addr6.s6_addr16[0] = htons(b1);
+ addr6.s6_addr16[1] = htons(b2);
+ addr6.s6_addr16[2] = htons(b3);
+ addr6.s6_addr16[3] = htons(b4);
+ addr6.s6_addr16[4] = htons(b5);
+ addr6.s6_addr16[5] = htons(b6);
+ addr6.s6_addr16[6] = htons(b7);
+ addr6.s6_addr16[7] = htons(b8);
+ } else
return -EINVAL;
expiry = get_expiry(&mesg);
@@ -215,10 +240,7 @@ static int ip_map_parse(struct cache_detail *cd,
} else
dom = NULL;
- addr.s_addr =
- htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
-
- ipmp = ip_map_lookup(class,addr);
+ ipmp = ip_map_lookup(class, &addr6);
if (ipmp) {
err = ip_map_update(ipmp,
container_of(dom, struct unix_domain, h),
@@ -238,7 +260,7 @@ static int ip_map_show(struct seq_file *m,
struct cache_head *h)
{
struct ip_map *im;
- struct in_addr addr;
+ struct in6_addr addr6;
char *dom = "-no-domain-";
if (h == NULL) {
@@ -247,20 +269,24 @@ static int ip_map_show(struct seq_file *m,
}
im = container_of(h, struct ip_map, h);
/* class addr domain */
- addr = im->m_addr;
+ ipv6_addr_copy(&addr6, &im->m_addr);
if (test_bit(CACHE_VALID, &h->flags) &&
!test_bit(CACHE_NEGATIVE, &h->flags))
dom = im->m_client->h.name;
- seq_printf(m, "%s %d.%d.%d.%d %s\n",
- im->m_class,
- ntohl(addr.s_addr) >> 24 & 0xff,
- ntohl(addr.s_addr) >> 16 & 0xff,
- ntohl(addr.s_addr) >> 8 & 0xff,
- ntohl(addr.s_addr) >> 0 & 0xff,
- dom
- );
+ if (ipv6_addr_v4mapped(&addr6)) {
+ seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
+ im->m_class,
+ ntohl(addr6.s6_addr32[3]) >> 24 & 0xff,
+ ntohl(addr6.s6_addr32[3]) >> 16 & 0xff,
+ ntohl(addr6.s6_addr32[3]) >> 8 & 0xff,
+ ntohl(addr6.s6_addr32[3]) >> 0 & 0xff,
+ dom);
+ } else {
+ seq_printf(m, "%s" NIP6_FMT "%s\n",
+ im->m_class, NIP6(addr6), dom);
+ }
return 0;
}
@@ -280,16 +306,16 @@ struct cache_detail ip_map_cache = {
.alloc = ip_map_alloc,
};
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
{
struct ip_map ip;
struct cache_head *ch;
strcpy(ip.m_class, class);
- ip.m_addr = addr;
+ ipv6_addr_copy(&ip.m_addr, addr);
ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
hash_str(class, IP_HASHBITS) ^
- hash_ip(addr.s_addr));
+ hash_ip6(addr));
if (ch)
return container_of(ch, struct ip_map, h);
@@ -318,14 +344,14 @@ static int ip_map_update(struct ip_map *ipm,
struct unix_domain *udom, time_t ex
ch = sunrpc_cache_update(&ip_map_cache,
&ip.h, &ipm->h,
hash_str(ipm->m_class, IP_HASHBITS) ^
- hash_ip(ipm->m_addr.s_addr));
+ hash_ip6(&ipm->m_addr));
if (!ch)
return -ENOMEM;
cache_put(ch, &ip_map_cache);
return 0;
}
-int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
{
struct unix_domain *udom;
struct ip_map *ipmp;
@@ -352,7 +378,7 @@ int auth_unix_forget_old(struct auth_domain *dom)
return 0;
}
-struct auth_domain *auth_unix_lookup(struct in_addr addr)
+struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
{
struct ip_map *ipm;
struct auth_domain *rv;
@@ -641,9 +667,23 @@ static int unix_gid_find(uid_t uid, struct
group_info **gip,
int
svcauth_unix_set_client(struct svc_rqst *rqstp)
{
- struct sockaddr_in *sin = svc_addr_in(rqstp);
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6, sin6_storage;
struct ip_map *ipm;
+ switch (rqstp->rq_addr.ss_family) {
+ case AF_INET:
+ sin = svc_addr_in(rqstp);
+ sin6 = &sin6_storage;
+ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &sin6->sin6_addr);
+ break;
+ case AF_INET6:
+ sin6 = svc_addr_in6(rqstp);
+ break;
+ default:
+ BUG();
+ }
+
rqstp->rq_client = NULL;
if (rqstp->rq_proc == 0)
return SVC_OK;
@@ -651,7 +691,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
ipm = ip_map_cached_get(rqstp);
if (ipm == NULL)
ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
- sin->sin_addr);
+ &sin6->sin6_addr);
if (ipm == NULL)
return SVC_DENIED;
--
********************************
Aurelien Charbon
Linux NFSv4 team
Bull SAS
Echirolles - France
http://nfsv4.bullopensource.org/
********************************
[-- Attachment #2: nfs.ipv6.patch --]
[-- Type: text/x-patch, Size: 13502 bytes --]
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 66d0aeb..c47ba77 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -35,6 +35,7 @@
#include <linux/lockd/bind.h>
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/gss_api.h>
+#include <net/ipv6.h>
#define NFSDDBG_FACILITY NFSDDBG_EXPORT
@@ -1556,6 +1557,7 @@ exp_addclient(struct nfsctl_client *ncp)
{
struct auth_domain *dom;
int i, err;
+ struct in6_addr in6;
/* First, consistency check. */
err = -EINVAL;
@@ -1574,9 +1576,10 @@ exp_addclient(struct nfsctl_client *ncp)
goto out_unlock;
/* Insert client into hashtable. */
- for (i = 0; i < ncp->cl_naddr; i++)
- auth_unix_add_addr(ncp->cl_addrlist[i], dom);
-
+ for (i = 0; i < ncp->cl_naddr; i++) {
+ ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &in6);
+ auth_unix_add_addr(&in6, dom);
+ }
auth_unix_forget_old(dom);
auth_domain_put(dom);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 77dc989..5cb5f0d 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -37,6 +37,7 @@
#include <linux/nfsd/syscall.h>
#include <asm/uaccess.h>
+#include <net/ipv6.h>
/*
* We have a single directory with 9 nodes in it.
@@ -219,24 +220,37 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
{
struct nfsctl_fsparm *data;
struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
struct auth_domain *clp;
int err = 0;
struct knfsd_fh *res;
+ struct in6_addr in6;
if (size < sizeof(*data))
return -EINVAL;
data = (struct nfsctl_fsparm*)buf;
err = -EPROTONOSUPPORT;
- if (data->gd_addr.sa_family != AF_INET)
+ switch (data->gd_addr.sa_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)&data->gd_addr;
+ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&data->gd_addr;
+ ipv6_addr_copy(&in6, &sin6->sin6_addr);
+ break;
+ default:
goto out;
- sin = (struct sockaddr_in *)&data->gd_addr;
+ }
+
if (data->gd_maxlen > NFS3_FHSIZE)
data->gd_maxlen = NFS3_FHSIZE;
res = (struct knfsd_fh*)buf;
exp_readlock();
- if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+ if (!(clp = auth_unix_lookup(&in6)))
err = -EPERM;
else {
err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
@@ -253,25 +267,41 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
{
struct nfsctl_fdparm *data;
struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
struct auth_domain *clp;
int err = 0;
struct knfsd_fh fh;
char *res;
+ struct in6_addr in6;
if (size < sizeof(*data))
return -EINVAL;
data = (struct nfsctl_fdparm*)buf;
err = -EPROTONOSUPPORT;
- if (data->gd_addr.sa_family != AF_INET)
+ if (data->gd_addr.sa_family != AF_INET &&
+ data->gd_addr.sa_family != AF_INET6)
goto out;
err = -EINVAL;
if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
goto out;
res = buf;
- sin = (struct sockaddr_in *)&data->gd_addr;
exp_readlock();
- if (!(clp = auth_unix_lookup(sin->sin_addr)))
+
+ switch (data->gd_addr.sa_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)&data->gd_addr;
+ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&data->gd_addr;
+ ipv6_addr_copy(&in6, &sin6->sin6_addr);
+ break;
+ default:
+ goto out;
+ }
+
+ if (!(clp = auth_unix_lookup(&in6)))
err = -EPERM;
else {
err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
index 22e1ef8..64ecb93 100644
--- a/include/linux/sunrpc/svcauth.h
+++ b/include/linux/sunrpc/svcauth.h
@@ -15,6 +15,7 @@
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/cache.h>
#include <linux/hash.h>
+#include <net/ipv6.h>
#define SVC_CRED_NGROUPS 32
struct svc_cred {
@@ -120,10 +121,10 @@ extern void svc_auth_unregister(rpc_authflavor_t flavor);
extern struct auth_domain *unix_domain_find(char *name);
extern void auth_domain_put(struct auth_domain *item);
-extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom);
+extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
extern struct auth_domain *auth_domain_find(char *name);
-extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
+extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
extern int auth_unix_forget_old(struct auth_domain *dom);
extern void svcauth_unix_purge(void);
extern void svcauth_unix_info_release(void *);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index ae328b6..366fdca 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -16,6 +16,7 @@
#define _NET_IPV6_H
#include <linux/ipv6.h>
+#include <linux/in.h>
#include <linux/hardirq.h>
#include <net/if_inet6.h>
#include <net/ndisc.h>
@@ -400,6 +401,15 @@ static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
a->s6_addr32[2] == htonl(0x0000ffff));
}
+static inline void ipv6_addr_set_v4mapped(const __be32 addr,
+ struct in6_addr *v4mapped)
+{
+ ipv6_addr_set(v4mapped,
+ 0, 0,
+ __constant_htonl(0x0000FFFF),
+ addr);
+}
+
/*
* find the first different bit between two addresses
* length of address must be a multiple of 32bits
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 4114794..a40d769 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -11,6 +11,7 @@
#include <linux/hash.h>
#include <linux/string.h>
#include <net/sock.h>
+#include <net/ipv6.h>
#define RPCDBG_FACILITY RPCDBG_AUTH
@@ -84,7 +85,7 @@ static void svcauth_unix_domain_release(struct auth_domain *dom)
struct ip_map {
struct cache_head h;
char m_class[8]; /* e.g. "nfsd" */
- struct in_addr m_addr;
+ struct in6_addr m_addr;
struct unix_domain *m_client;
int m_add_change;
};
@@ -101,7 +102,6 @@ static void ip_map_put(struct kref *kref)
kfree(im);
}
-#if IP_HASHBITS == 8
/* hash_long on a 64 bit machine is currently REALLY BAD for
* IP addresses in reverse-endian (i.e. on a little-endian machine).
* So use a trivial but reliable hash instead
@@ -111,13 +111,20 @@ static inline int hash_ip(__be32 ip)
int hash = (__force u32)ip ^ ((__force u32)ip>>16);
return (hash ^ (hash>>8)) & 0xff;
}
-#endif
+
+static inline int hash_ip6(struct in6_addr *ip6)
+{
+ return (hash_ip(ip6->s6_addr32[0]) ^
+ hash_ip(ip6->s6_addr32[1]) ^
+ hash_ip(ip6->s6_addr32[2]) ^
+ hash_ip(ip6->s6_addr32[3]));
+}
static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
{
struct ip_map *orig = container_of(corig, struct ip_map, h);
struct ip_map *new = container_of(cnew, struct ip_map, h);
return strcmp(orig->m_class, new->m_class) == 0
- && orig->m_addr.s_addr == new->m_addr.s_addr;
+ && ipv6_addr_equal(&orig->m_addr, &new->m_addr);
}
static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
{
@@ -125,7 +132,7 @@ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
struct ip_map *item = container_of(citem, struct ip_map, h);
strcpy(new->m_class, item->m_class);
- new->m_addr.s_addr = item->m_addr.s_addr;
+ ipv6_addr_copy(&new->m_addr, &item->m_addr);
}
static void update(struct cache_head *cnew, struct cache_head *citem)
{
@@ -149,22 +156,24 @@ static void ip_map_request(struct cache_detail *cd,
struct cache_head *h,
char **bpp, int *blen)
{
- char text_addr[20];
+ char text_addr[40];
struct ip_map *im = container_of(h, struct ip_map, h);
- __be32 addr = im->m_addr.s_addr;
-
- snprintf(text_addr, 20, "%u.%u.%u.%u",
- ntohl(addr) >> 24 & 0xff,
- ntohl(addr) >> 16 & 0xff,
- ntohl(addr) >> 8 & 0xff,
- ntohl(addr) >> 0 & 0xff);
+ if (ipv6_addr_v4mapped(&(im->m_addr))) {
+ snprintf(text_addr, 20, NIPQUAD_FMT,
+ ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
+ ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
+ ntohl(im->m_addr.s6_addr32[3]) >> 8 & 0xff,
+ ntohl(im->m_addr.s6_addr32[3]) >> 0 & 0xff);
+ } else {
+ snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
+ }
qword_add(bpp, blen, im->m_class);
qword_add(bpp, blen, text_addr);
(*bpp)[-1] = '\n';
}
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
static int ip_map_parse(struct cache_detail *cd,
@@ -175,10 +184,10 @@ static int ip_map_parse(struct cache_detail *cd,
* for scratch: */
char *buf = mesg;
int len;
- int b1,b2,b3,b4;
+ int b1, b2, b3, b4, b5, b6, b7, b8;
char c;
char class[8];
- struct in_addr addr;
+ struct in6_addr addr6;
int err;
struct ip_map *ipmp;
@@ -197,7 +206,23 @@ static int ip_map_parse(struct cache_detail *cd,
len = qword_get(&mesg, buf, mlen);
if (len <= 0) return -EINVAL;
- if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
+ if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
+ addr6.s6_addr32[0] = 0;
+ addr6.s6_addr32[1] = 0;
+ addr6.s6_addr32[2] = htonl(0xffff);
+ addr6.s6_addr32[3] =
+ htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
+ } else if (sscanf(buf, NIP6_FMT "%c",
+ &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
+ addr6.s6_addr16[0] = htons(b1);
+ addr6.s6_addr16[1] = htons(b2);
+ addr6.s6_addr16[2] = htons(b3);
+ addr6.s6_addr16[3] = htons(b4);
+ addr6.s6_addr16[4] = htons(b5);
+ addr6.s6_addr16[5] = htons(b6);
+ addr6.s6_addr16[6] = htons(b7);
+ addr6.s6_addr16[7] = htons(b8);
+ } else
return -EINVAL;
expiry = get_expiry(&mesg);
@@ -215,10 +240,7 @@ static int ip_map_parse(struct cache_detail *cd,
} else
dom = NULL;
- addr.s_addr =
- htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
-
- ipmp = ip_map_lookup(class,addr);
+ ipmp = ip_map_lookup(class, &addr6);
if (ipmp) {
err = ip_map_update(ipmp,
container_of(dom, struct unix_domain, h),
@@ -238,7 +260,7 @@ static int ip_map_show(struct seq_file *m,
struct cache_head *h)
{
struct ip_map *im;
- struct in_addr addr;
+ struct in6_addr addr6;
char *dom = "-no-domain-";
if (h == NULL) {
@@ -247,20 +269,24 @@ static int ip_map_show(struct seq_file *m,
}
im = container_of(h, struct ip_map, h);
/* class addr domain */
- addr = im->m_addr;
+ ipv6_addr_copy(&addr6, &im->m_addr);
if (test_bit(CACHE_VALID, &h->flags) &&
!test_bit(CACHE_NEGATIVE, &h->flags))
dom = im->m_client->h.name;
- seq_printf(m, "%s %d.%d.%d.%d %s\n",
- im->m_class,
- ntohl(addr.s_addr) >> 24 & 0xff,
- ntohl(addr.s_addr) >> 16 & 0xff,
- ntohl(addr.s_addr) >> 8 & 0xff,
- ntohl(addr.s_addr) >> 0 & 0xff,
- dom
- );
+ if (ipv6_addr_v4mapped(&addr6)) {
+ seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
+ im->m_class,
+ ntohl(addr6.s6_addr32[3]) >> 24 & 0xff,
+ ntohl(addr6.s6_addr32[3]) >> 16 & 0xff,
+ ntohl(addr6.s6_addr32[3]) >> 8 & 0xff,
+ ntohl(addr6.s6_addr32[3]) >> 0 & 0xff,
+ dom);
+ } else {
+ seq_printf(m, "%s" NIP6_FMT "%s\n",
+ im->m_class, NIP6(addr6), dom);
+ }
return 0;
}
@@ -280,16 +306,16 @@ struct cache_detail ip_map_cache = {
.alloc = ip_map_alloc,
};
-static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
+static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
{
struct ip_map ip;
struct cache_head *ch;
strcpy(ip.m_class, class);
- ip.m_addr = addr;
+ ipv6_addr_copy(&ip.m_addr, addr);
ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
hash_str(class, IP_HASHBITS) ^
- hash_ip(addr.s_addr));
+ hash_ip6(addr));
if (ch)
return container_of(ch, struct ip_map, h);
@@ -318,14 +344,14 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex
ch = sunrpc_cache_update(&ip_map_cache,
&ip.h, &ipm->h,
hash_str(ipm->m_class, IP_HASHBITS) ^
- hash_ip(ipm->m_addr.s_addr));
+ hash_ip6(&ipm->m_addr));
if (!ch)
return -ENOMEM;
cache_put(ch, &ip_map_cache);
return 0;
}
-int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
+int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
{
struct unix_domain *udom;
struct ip_map *ipmp;
@@ -352,7 +378,7 @@ int auth_unix_forget_old(struct auth_domain *dom)
return 0;
}
-struct auth_domain *auth_unix_lookup(struct in_addr addr)
+struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
{
struct ip_map *ipm;
struct auth_domain *rv;
@@ -641,9 +667,23 @@ static int unix_gid_find(uid_t uid, struct group_info **gip,
int
svcauth_unix_set_client(struct svc_rqst *rqstp)
{
- struct sockaddr_in *sin = svc_addr_in(rqstp);
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6, sin6_storage;
struct ip_map *ipm;
+ switch (rqstp->rq_addr.ss_family) {
+ case AF_INET:
+ sin = svc_addr_in(rqstp);
+ sin6 = &sin6_storage;
+ ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &sin6->sin6_addr);
+ break;
+ case AF_INET6:
+ sin6 = svc_addr_in6(rqstp);
+ break;
+ default:
+ BUG();
+ }
+
rqstp->rq_client = NULL;
if (rqstp->rq_proc == 0)
return SVC_OK;
@@ -651,7 +691,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
ipm = ip_map_cached_get(rqstp);
if (ipm == NULL)
ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
- sin->sin_addr);
+ &sin6->sin6_addr);
if (ipm == NULL)
return SVC_DENIED;
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
NFSv4 mailing list
NFSv4@linux-nfs.org
http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox