* Re: [PATCH] Export smbios strings associated with onboard devices to sysfs
From: Alex Chiang @ 2010-03-08 17:34 UTC (permalink / raw)
To: Narendra K
Cc: matt_domsch, netdev, linux-hotplug, linux-pci, jordan_hargrave,
sandeep_k_shandilya, charles_rose, shyam_iyer
In-Reply-To: <20100302173302.GA20936@mock.linuxdev.us.dell.com>
* Narendra K <Narendra_K@dell.com>:
>
> Resending the patch with review comments incorporated.
>
> Signed-off-by: Jordan Hargrave <Jordan_Hargrave@dell.com>
> Signed-off-by: Narendra K <Narendra_K@dell.com>
> ---
> drivers/firmware/dmi_scan.c | 23 ++++++++++++++++++
> drivers/pci/pci-sysfs.c | 54 +++++++++++++++++++++++++++++++++++++++++++
> include/linux/dmi.h | 9 +++++++
> 3 files changed, 86 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
> index 31b983d..1d10663 100644
> --- a/drivers/firmware/dmi_scan.c
> +++ b/drivers/firmware/dmi_scan.c
> @@ -278,6 +278,28 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
> list_add_tail(&dev->list, &dmi_devices);
> }
>
> +static void __init dmi_save_devslot(int id, int seg, int bus, int devfn, const char *name)
> +{
> + struct dmi_devslot *slot;
> +
> + slot = dmi_alloc(sizeof(*slot) + strlen(name) + 1);
> + if (!slot) {
> + printk(KERN_ERR "dmi_save_devslot: out of memory.\n");
> + return;
> + }
> + slot->id = id;
> + slot->seg = seg;
> + slot->bus = bus;
> + slot->devfn = devfn;
> +
> + strcpy((char *)&slot[1], name);
> + slot->dev.type = DMI_DEV_TYPE_DEVSLOT;
> + slot->dev.name = &slot[1];
This needs a cast, else you'll get a warning:
slot->dev.name = (char *)&slot[1];
Also, when I was playing with your patchset, I noticed that you
should probably add this hunk too:
@@ -334,6 +359,7 @@ static void __init dmi_decode(const struct dmi_header *dm, v
break;
case 41: /* Onboard Devices Extended Information */
dmi_save_extended_devices(dm);
+ break;
}
}
> +#ifdef CONFIG_DMI
> +#include <linux/dmi.h>
> +static ssize_t
> +smbiosname_string_is_valid(struct device *dev, char *buf)
> +{
> + struct pci_dev *pdev = to_pci_dev(dev);
> + struct dmi_device *dmi;
This needs to be a const struct dmi_device, else you get a
warning.
> + struct dmi_devslot *dslot;
> + int bus;
> + int devfn;
> +
> + bus = pdev->bus->number;
> + devfn = pdev->devfn;
> +
> + dmi = NULL;
> + while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEVSLOT, NULL, dmi)) != NULL) {
> + dslot = dmi->device_data;
> + if (dslot && dslot->bus == bus && dslot->devfn == devfn) {
> + if (buf)
> + return scnprintf(buf, PAGE_SIZE, "%s\n", dmi->name);
Whitespace seems messed up here?
> + return strlen(dmi->name);
> + }
> + }
> +}
> +
> +static ssize_t
> +smbiosname_show(struct device *dev, struct device_attribute *attr, char *buf)
> +{
> + return smbiosname_string_is_valid(dev, buf);
> +
> +}
> +
> +struct smbios_attribute {
> + struct attribute attr;
> + ssize_t(*show) (struct device * edev, char *buf);
> + int (*test) (struct device * edev, char *buf);
> +};
> +
> +#define SMBIOSNAME_DEVICE_ATTR(_name, _mode, _show, _test) \
> +struct smbios_attribute smbios_attr_##_name = { \
> + .attr = {.name = __stringify(_name), .mode = _mode }, \
> + .show = _show, \
> + .test = _test, \
> +};
> +
> +static SMBIOSNAME_DEVICE_ATTR(smbiosname, 0444, smbiosname_show, smbiosname_string_is_valid);
> +#endif
> +
After a discussion on irc, some folks thought that changing the
name of this attribute to 'label' would be a much better name
than smbiosname.
/ac
^ permalink raw reply
* Re: [RFC][PATCH] ns: Syscalls for better namespace sharing control.
From: Eric W. Biederman @ 2010-03-08 17:29 UTC (permalink / raw)
To: Daniel Lezcano
Cc: Pavel Emelyanov, Sukadev Bhattiprolu, Serge Hallyn,
Linux Netdev List, containers, Netfilter Development Mailinglist,
Ben Greear
In-Reply-To: <4B952BBE.6070507@free.fr>
Daniel Lezcano <daniel.lezcano@free.fr> writes:
> Eric W. Biederman wrote:
>> I have take an snapshot of my development tree and placed it at.
>>
>>
>> git://git.kernel.org/pub/scm/linux/people/ebiederm/linux-2.6.33-nsfd-v5.git
>>
>
> Hi Eric,
>
> thanks for the pointer.
>
> I tried to boot the kernel under qemu and I got this oops:
I am clearly running an old userspace on my test machine. No udev.
It looks like udev has a long standing netlink misfeature, where
it does not initializing NETLINK_CB....
>From 8d85e3ab88718eda3d94cf8e1be14b69dae2b8f1 Mon Sep 17 00:00:00 2001
From: Eric W. Biederman <ebiederm@xmission.com>
Date: Mon, 8 Mar 2010 09:25:20 -0800
Subject: [PATCH] kobject_uevent: Use the netlink allocator helper...
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
lib/kobject_uevent.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 920a3ca..b8229cc 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -216,7 +216,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
/* allocate message with the maximum possible size */
len = strlen(action_string) + strlen(devpath) + 2;
- skb = alloc_skb(len + env->buflen, GFP_KERNEL);
+ skb = nlmsg_new(len + env->buflen, GFP_KERNEL);
if (skb) {
char *scratch;
--
1.6.5.2.143.g8cc62
^ permalink raw reply related
* Re: [RFC][PATCH] ns: Syscalls for better namespace sharing control.
From: Serge E. Hallyn @ 2010-03-08 17:07 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Daniel Lezcano, Pavel Emelyanov, Sukadev Bhattiprolu,
Linux Netdev List, containers, Netfilter Development Mailinglist,
Ben Greear
In-Reply-To: <m1fx4bxlfy.fsf@fess.ebiederm.org>
Quoting Eric W. Biederman (ebiederm@xmission.com):
>
> I have take an snapshot of my development tree and placed it at.
>
>
> git://git.kernel.org/pub/scm/linux/people/ebiederm/linux-2.6.33-nsfd-v5.git
>
>
> >> I am going to explore a bit more. Given that nsfd is using the same
> >> permission checks as a proc file, I think I can just make it a proc
> >> file. Something like "/proc/<pid>/ns/net". With a little luck that
> >> won't suck too badly.
> >>
> > Ah ! yes. Good idea.
>
> It is a hair more code to use proc files but nothing worth counting.
>
> Probably the biggest thing I am aware of right now in my development
> tree is in getting uids to pass properly between unix domain sockets
> I would up writing this cred_to_ucred function.
>
> Serge can you take a look and check my logic, and do you have
> any idea of where we should place something like pid_vnr but
> for the uid namespace?
Well my first thought was user_namespace, but I'm thinking kernel/cred.c is
the best place for it.
> void cred_to_ucred(struct pid *pid, const struct cred *cred,
> struct ucred *ucred)
> {
> ucred->pid = pid_vnr(pid);
> ucred->uid = ucred->gid = -1;
> if (cred) {
> struct user_namespace *cred_ns = cred->user->user_ns;
> struct user_namespace *current_ns = current_user_ns();
> struct user_namespace *tmp;
>
> if (likely(cred_ns == current_ns)) {
> ucred->uid = cred->euid;
> ucred->gid = cred->egid;
> } else {
> /* Is cred in a child user namespace */
> tmp = cred_ns;
> do {
> tmp = tmp->creator->user_ns;
> if (tmp == current_ns) {
Hmm, I think you want to catch one level up - so the creator itself
is in current_user_ns, so
do {
if (tmp->creator->user_ns == current_ns) {
ucred->uid = tmp->creator->uid;
ucred->gid = tmp->creator_gid;
return;
}
tmp = tmp->creator->user_ns;
} while (tmp != &init_user_ns);
> ucred->uid = tmp->creator->uid;
> ucred->gid = overflowgid;
should we start recording a user_ns->creator_gid
instead?
> return;
> }
> } while (tmp != &init_user_ns);
>
> /* Is cred the creator of my user namespace,
> * or the creator of one of it's parents?
> */
> for( tmp = current_ns; tmp != &init_user_ns;
> tmp = tmp->creator->user_ns) {
> if (cred->user == tmp->creator) {
> ucred->uid = 0;
> ucred->gid = 0;
> return;
> }
> }
That looks right.
> /* No user namespace relationship so no mapping */
> ucred->uid = overflowuid;
> ucred->gid = overflowgid;
> }
> }
> }
>
> Eric
^ permalink raw reply
* Re: [net-next-2.6 PATCH v2] net: consolidate netif_needs_gso() checks
From: John Fastabend @ 2010-03-08 16:56 UTC (permalink / raw)
To: Herbert Xu
Cc: David Miller, Kirsher, Jeffrey T, netdev@vger.kernel.org,
gospo@redhat.com
In-Reply-To: <20100307014324.GA19589@gondor.apana.org.au>
Herbert Xu wrote:
> On Sat, Mar 06, 2010 at 11:27:50AM -0800, John Fastabend wrote:
>
>> It looks like dev_gso_segment() could be used to "Verify header
>> integrity only" according to the comment? If this is true I think the
>> logic should probably be
>>
>> if (netif_needs_gso(dev, skb)) {
>> if (unlikely(dev_gso_segment(skb)))
>> goto out_kfree_skb;
>> if (skb->next)
>> goto gso;
>> } do your thing
>>
>>
>>
>> That way we linearize the skb if necessary in the case were
>> dev_gso_segment() only verifies the header and does not return a list of
>> segments.
>>
>
> If we needed to linearise the skb then dev_gso_segment should
> perform the segmentation. Is there a case where it doesn't?
>
> Cheers,
Nope as far as I can tell all cases are covered my concerns were
unfounded. Thanks for the review, I'll get this updated and resent.
-John.
^ permalink raw reply
* Re: [RFC][PATCH] ns: Syscalls for better namespace sharing control.
From: Daniel Lezcano @ 2010-03-08 16:54 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Pavel Emelyanov, Sukadev Bhattiprolu, Serge Hallyn,
Linux Netdev List, containers, Netfilter Development Mailinglist,
Ben Greear
In-Reply-To: <m1fx4bxlfy.fsf@fess.ebiederm.org>
Eric W. Biederman wrote:
> I have take an snapshot of my development tree and placed it at.
>
>
> git://git.kernel.org/pub/scm/linux/people/ebiederm/linux-2.6.33-nsfd-v5.git
>
Hi Eric,
thanks for the pointer.
I tried to boot the kernel under qemu and I got this oops:
Loading /lib/kbd/keymaps/i386/azerty/fr.map
Creating block device nodes.
Creating character device nodes.
Making device-mapper control node
BUG: unable to handle kernel NULL pointer dereference at (null)
IP: [<ffffffff812df7e7>] netlink_broadcast+0x1bd/0x384
PGD 3cfd0067 PUD 3cfc1067 PMD 0
Oops: 0002 [#1] DEBUG_PAGEALLOC
last sysfs file: /sys/class/firmware/timeout
CPU 0
Pid: 841, comm: modprobe Not tainted 2.6.33 #1 /
RIP: 0010:[<ffffffff812df7e7>] [<ffffffff812df7e7>]
netlink_broadcast+0x1bd/0x384
RSP: 0018:ffff88003cfc3ca8 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffff88003ce947f0 RCX: ffff88003cf877f0
RDX: ffff88003f939dd0 RSI: ffff88003f939ef0 RDI: ffff88003f939e00
RBP: ffff88003cfc3d18 R08: ffff88003f939d98 R09: ffff88003f939e88
R10: ffff88003cf87818 R11: 0000000000000286 R12: ffff88003f939d98
R13: ffff88003f939e88 R14: ffff88003ce94818 R15: ffff88003ce94800
FS: 00007f23a90a06f0(0000) GS:ffffffff8161b000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 000000003cfcd000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process modprobe (pid: 841, threadinfo ffff88003cfc2000, task
ffff88003d1db058)
Stack:
0000000000000270 00000000000000d0 ffff88003f9377f0 ffffffff8203d630
<0> ffff88003f939f5c 0000000000000000 0000000000000001 0000000000000000
<0> ffff88003cf03000 0000000000000020 0000000000000004 ffff88003f939e88
Call Trace:
[<ffffffff8121c1bd>] kobject_uevent_env+0x414/0x59b
[<ffffffff81117432>] ? sysfs_create_file+0x25/0x27
[<ffffffff8105eb13>] ? module_add_modinfo_attrs+0xd6/0xfc
[<ffffffff8121c34f>] kobject_uevent+0xb/0xd
[<ffffffff8105eba4>] mod_sysfs_setup+0x6b/0x99
[<ffffffff810602aa>] load_module+0x12a2/0x16f1
[<ffffffff81060b34>] sys_init_module+0x60/0x230
[<ffffffff81002928>] system_call_fastpath+0x16/0x1b
Code: 00 ff c8 74 2a 8b 75 98 4c 89 ef e8 22 f8 fd ff 48 85 c0 49 89 c4
74 3c 48 8d 50 38 48 8b 40 38 48 85 c0 74 0
2 ff 00 48 8b 42 08 <ff> 00 eb 4f 48 8b 55 b0 ff 02 49 83 7d 10 00 74 08
4c 89 ef e8
RIP [<ffffffff812df7e7>] netlink_broadcast+0x1bd/0x384
RSP <ffff88003cfc3ca8>
CR2: 0000000000000000
---[ end trace 979d62b87f68fab3 ]---
netlink_recvmsg: missing NETLINK_CB proto: 15 pid: 0 dsg_group: 1
destructor = (null)
nlmsghdr: len=1080321121 type=27951 flags=646f seq=795176053 pid=1769169779
I will try to investigate further later - kid duty :)
-- Daniel
^ permalink raw reply
* Get back to me
From: Mr Evans Green @ 2010-03-08 16:29 UTC (permalink / raw)
Good Day.
Although you might be apprehensive about my email as we have not met before, I
am Mr Evans Green,I am a Banker i work with Bank Of England,There is
the sum of
$20,600,000.00 in my Bank "Bank Of England"London, There were no beneficiaries
stated concerning these funds which means no one would ever come forward to
claim it.
That is why I ask that we work together so as to have the sum
transfered out of
my Bank into your Bank Account or any other account of your chioce. I will be
pleased to see if you can help me and also be a good and trusted person.
Once the funds have been transferred to your Nominated Bank Account we shall
then share in the ratio of 60% for me, 40% for you.do send me a mail
as soon as
possible for more details here is my email address:evans195604@gncn.net
Regards
Mr Evans Green.
^ permalink raw reply
* RE: TCP_COOKIE_TRANSACTIONS synack data
From: Penttilä Mika @ 2010-03-08 16:33 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev@vger.kernel.org, William Allen Simpson
In-Reply-To: <1268064070.6148.104.camel@edumazet-laptop>
>
> Le lundi 08 mars 2010 à 16:27 +0200, Penttilä Mika a écrit :
> > The TCP_COOKIE_TRANSACTIONS synack data seems pretty unsafe atm.
> > >From tcp_make_synack():
> >
> >
> > u8 *buf = skb_put(skb, cvp->s_data_desired);
> >
> > /* copy data directly from the listening socket. */
> > memcpy(buf, cvp->s_data_payload, cvp->s_data_desired);
> >
> >
> > The skb here is allocated for MAX_TCP_HEADER + 15 and synack data
> could be as long as TCP_MSS_DEFAULT, panic():ing at the skb_put().
> >
>
> Indeed, since start of december 2009.
>
> Do you plan to provide a patch do you prefer someone else take care of
> it ?
>
I'm not planning to provide a patch at least very soon so I think someone else can provide a quicker fix.
> Thanks
>
>
^ permalink raw reply
* Re: drivers/net/mac8390.c: Remove useless memcpy casting
From: Joe Perches @ 2010-03-08 16:16 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: David S. Miller, netdev, Linux Kernel Mailing List, Linux/m68k
In-Reply-To: <10f740e81003070119s3eb433d9r4f1cc79e59d56316@mail.gmail.com>
On Sun, 2010-03-07 at 10:19 +0100, Geert Uytterhoeven wrote:
> ... hence you introduced 3 compiler warnings:
>
> drivers/net/mac8390.c:249: warning: passing argument 1 of
> '__builtin_memcpy' makes pointer from integer without a cast
> drivers/net/mac8390.c:254: warning: passing argument 1 of
> 'word_memcpy_tocard' makes pointer from integer without a cast
> drivers/net/mac8390.c:256: warning: passing argument 2 of
> 'word_memcpy_fromcard' makes pointer from integer without a cast
Thanks, I'll submit a patch to fix it by tomorrow or so.
^ permalink raw reply
* Strange OOPS in 2.6.33
From: Joakim Tjernlund @ 2010-03-08 16:04 UTC (permalink / raw)
To: netdev
Tried the ppc list but no luck so I figure I should try here instead:
I get this OOPS after coldstarting a
board every now and then:
Unable to handle kernel paging request for unknown fault
Faulting instruction address: 0xc020e2b4
Oops: Kernel access of bad area, sig: 11 [#1]
TMCUTU
Modules linked in:
NIP: c020e2b4 LR: c020e274 CTR: 00000000
REGS: c7a41b40 TRAP: 0600 Not tainted (2.6.33)
MSR: 00009032 <EE,ME,IR,DR> CR: 28002424 XER: 00000000
DAR: 09f52312, DSISR: 00000120
TASK = c7889940[420] 'syslogd' THREAD: c7a40000
GPR00: 09f52312 c7a41bf0 c7889940 00000000 00000002 c7a41c40 c02734ac c78acc68
GPR08: c7a41c00 c78acc00 00000000 09f5214b c796e3d4 1001f444 00000000 bfe78700
GPR16: bfe77400 bfe77ee0 bfe773f8 00000021 0ffef130 00000000 c7a41df0 00000000
GPR24: 00000000 c7a41cf0 c7a41c70 00000011 7f000001 09f5214a c034a5cc c7a41c00
NIP [c020e2b4] ip_dev_find+0x90/0xf0
LR [c020e274] ip_dev_find+0x50/0xf0
Call Trace:
[c7a41bf0] [c020e274] ip_dev_find+0x50/0xf0 (unreliable)
[c7a41c60] [c01dd86c] __ip_route_output_key+0x8d4/0xb00
[c7a41d50] [c01ddab8] ip_route_output_flow+0x1c/0xa0
[c7a41d60] [c01ff8a0] ip4_datagram_connect+0x17c/0x2b8
[c7a41e30] [c020a75c] inet_dgram_connect+0x5c/0xa8
[c7a41e50] [c01a5030] sys_connect+0x7c/0xcc
[c7a41f00] [c01a6008] sys_socketcall+0x128/0x214
[c7a41f40] [c0011800] ret_from_syscall+0x0/0x38
--- Exception: c01 at 0xff6e004
LR = 0xfe2dac0
Instruction dump:
bb810060 38210070 7c0803a6 4e800020 88010052 2f800002 409e0028 81210054
83a90068 2f9d0000 419e0018 381d01c8 <7d200028> 31290001 7d20012d 40a2fff4
---[ end trace 0824e85bac28e7e4 ]---
gdb says:
(gdb) list *0xc020e2b4
0xc020e2b4 is in ip_dev_find (/usr/local/src/BUILD/trunk/os2kernel/arch/powerpc/include/asm/atomic.h:106).
101
102 static __inline__ void atomic_inc(atomic_t *v)
103 {
104 int t;
105
106 __asm__ __volatile__(
107 "1: lwarx %0,0,%2 # atomic_inc\n\
108 addic %0,%0,1\n"
109 PPC405_ERR77(0,%2)
110 " stwcx. %0,0,%2 \n\
gdb) disass 0xc020e2b4 0xc020e2c4
Dump of assembler code from 0xc020e2b4 to 0xc020e2c4:
0xc020e2b4 <ip_dev_find+144>: lwarx r9,0,r0
0xc020e2b8 <ip_dev_find+148>: addic r9,r9,1
0xc020e2bc <ip_dev_find+152>: stwcx. r9,0,r0
0xc020e2c0 <ip_dev_find+156>: bne- 0xc020e2b4 <ip_dev_find+144>
This is on a MPC8321 CPU
gcc 3.4.6
Got a bit further, turns out that the dev ptr returned from
dev = FIB_RES_DEV(res) is bogus in ip_dev_find:
struct net_device * ip_dev_find(struct net *net, __be32 addr)
{
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
struct fib_result res;
struct net_device *dev = NULL;
struct fib_table *local_table;
#ifdef CONFIG_IP_MULTIPLE_TABLES
res.r = NULL;
#endif
local_table = fib_get_table(net, RT_TABLE_LOCAL);
if (!local_table || fib_table_lookup(local_table, &fl, &res))
return NULL;
if (res.type != RTN_LOCAL)
goto out;
dev = FIB_RES_DEV(res);
if (dev)
dev_hold(dev);
out:
fib_res_put(&res);
return dev;
}
I have no idea how to proceed from here. Problem happens when user space
makes its first access to eth0, in this case ntpdate. It is very hard to repeat
the problem so it feels like a race somewhere in interface bring up
I bring up ethernet at boot with:
~# m /proc/cmdline
root=/dev/mtdblock6 rw rootfstype=jffs2 ip=192.168.1.16:192.168.1.15:192.168.1.1:255.255.255.0::eth0:off console=ttyS0,115200 debug
^ permalink raw reply
* Re: TCP_COOKIE_TRANSACTIONS synack data
From: Eric Dumazet @ 2010-03-08 16:01 UTC (permalink / raw)
To: Penttilä Mika; +Cc: netdev@vger.kernel.org, William Allen Simpson
In-Reply-To: <2BC93087D531FF4A98881820AFE8AE7B74C409E1C3@jklmail01.ixonos.local>
Le lundi 08 mars 2010 à 16:27 +0200, Penttilä Mika a écrit :
> The TCP_COOKIE_TRANSACTIONS synack data seems pretty unsafe atm.
> >From tcp_make_synack():
>
>
> u8 *buf = skb_put(skb, cvp->s_data_desired);
>
> /* copy data directly from the listening socket. */
> memcpy(buf, cvp->s_data_payload, cvp->s_data_desired);
>
>
> The skb here is allocated for MAX_TCP_HEADER + 15 and synack data could be as long as TCP_MSS_DEFAULT, panic():ing at the skb_put().
>
Indeed, since start of december 2009.
Do you plan to provide a patch do you prefer someone else take care of
it ?
Thanks
^ permalink raw reply
* Re: [PATCH 1/1] bnx2x: Tx barriers and locks
From: Stanislaw Gruszka @ 2010-03-08 15:38 UTC (permalink / raw)
To: Michael Chan
Cc: Vladislav Zolotarov, netdev@vger.kernel.org, davem@davemloft.net,
Eilon Greenstein, Matthew Carlson
In-Reply-To: <1267550787.19491.109.camel@nseg_linux_HP1.broadcom.com>
On Tue, Mar 02, 2010 at 09:26:27AM -0800, Michael Chan wrote:
>
> On Tue, 2010-03-02 at 08:59 -0800, Stanislaw Gruszka wrote:
> > On Tue, Mar 02, 2010 at 08:18:44AM -0800, Michael Chan wrote:
> > > Stanislaw Gruszka wrote:
> > >
> > > > On Tue, Mar 02, 2010 at 04:50:59AM -0800, Vladislav Zolotarov wrote:
> > > > > Stanislaw barrier() is not a memory barrier - it's a
> > > > compiler barrier. I don't think removing it from
> > > > bnx2x_tx_avail() will improve anything. If u think I'm wrong,
> > > > could u, pls., provide a specific example.
> > > >
> > > > Only improvement is removing confusing code, And comment like
> > > > "Tell compiler that prod and cons can change" is even more
> > > > confusing. If you think I'm wrong, just tell as why that
> > > > barrier is needed :)
> > >
> > > The barrier (compiler barrier at least) is required in
> > > bnx2x_tx_avail(). The status block index can be updated by DMA and
> > > the compiler doesn't know it (because it is considered wrong to
> >
> > If you are telling status block index you mean which variable ?
>
> The fp-> fields which can be updated by NAPI poll based on new status
> block DMA.
So, we are talking about fp->tx_bd_prod and fp->tx_bd_cons.
> > > declare the status block as volatile). Near the end of
> > > bnx2x_start_xmit() where we call bnx2x_tx_avail() twice. It is
> > > possible that the compiler will optimize it and not look at the
> > > status block in memory the second time.
Still think barrier() in bnx2x_tx_avail is not necessary.
First of all, in what we have now in net-next-2.6 tree all fp->tx_bd_prod
modifications and bnx2x_tx_avail() function calls are done with
__netif_tx_lock taken, so we don't need any barriers for that. I'm omitting
here bnx2x_run_loopback() as this function is called when interface
is disabled, and bnx2x_stats_update() when output of bnx2x_tx_avail()
is printed in debug mode.
Regarding fp->tx_bd_cons: situation is a bit more complicated. It is modified
outside __netif_tx_lock protection and can happen in parallel with
bnx2x_start_xmit(). However barrier() in bnx2_tx_avail do not help when
fp->tx_bd_cons is modified on bnx2x_tx_int() on other cpu, since there
is no guarantees that registers/cache will be flushed on that cpu. Even
taking into account smp_wmb() after "fp->tx_bd_cons = bd_cons", as
smp_wmb() only guarantee preserve of ordering, not flushing registers/cache
in any particular time. For the same reason changing barrier() to smb_mb()
in bnx2x_tx_avail have no sense.
I plan to split my bnx2x patch into smaller peaces and post them. Small
patches perhaps will be more clean and You would not have objections
against :)
Stanislaw
^ permalink raw reply
* TCP_COOKIE_TRANSACTIONS synack data
From: Penttilä Mika @ 2010-03-08 14:27 UTC (permalink / raw)
To: netdev@vger.kernel.org
The TCP_COOKIE_TRANSACTIONS synack data seems pretty unsafe atm.
>From tcp_make_synack():
u8 *buf = skb_put(skb, cvp->s_data_desired);
/* copy data directly from the listening socket. */
memcpy(buf, cvp->s_data_payload, cvp->s_data_desired);
The skb here is allocated for MAX_TCP_HEADER + 15 and synack data could be as long as TCP_MSS_DEFAULT, panic():ing at the skb_put().
--Mika
^ permalink raw reply
* Re: KS8695: possible NAPI issue
From: Yegor Yefremov @ 2010-03-08 14:11 UTC (permalink / raw)
To: figo zhang; +Cc: Dick Hollenbeck, netdev, zealcook
In-Reply-To: <f69abfc31003080610m2701309ekd1a4a38ac2685703@mail.gmail.com>
This is ping afterwards:
debian:~# ping -c 1 192.168.1.38
PING 192.168.1.38 (192.168.1.38) 56(84) bytes of data.
tx ram addr = c371c202 , data len = 62
dst:00:18:f3:fe:84:84 src:00:04:d9:80:94:cd type: 0x0800
0xc371c20e : 45 00
0xc371c212 : 00 54 00 00 40 00 40 01 b6 f0 c0 a8 01 42 c0 a8
0xc371c222 : 01 26 08 00 65 51 1a 07 00 01 92 00 95 4b 5f 57
0xc371c232 : 07 00 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15
0xc371c242 : 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
0xc371c252 : 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35
0xc371c262 : 36 37
tx ram addr = c371c202 , data len = 2a
dst:00:18:f3:fe:84:84 src:00:04:d9:80:94:cd type: 0x0806
0xc371c20e : 00 01
0xc371c212 : 08 00 06 04 00 01 00 04 d9 80 94 cd c0 a8 01 42
0xc371c222 : 00 00 00 00 00 00 c0 a8 01 26
rx ram addr = c35d2020 , data len = 3c
dst:00:04:d9:80:94:cd src:00:18:f3:fe:84:84 type: 0x0806
0xc35d202c : 00 01
0xc35d2030 : 08 00 06 04 00 02 00 18 f3 fe 84 84 c0 a8 01 26
0xc35d2040 : 00 04 d9 80 94 cd c0 a8 01 42 00 00 00 00 00 00
0xc35d2050 : 00 00 00 00 00 00 00 00 00 00 00 00
--- 192.168.1.38 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
Yegor
^ permalink raw reply
* Re: KS8695: possible NAPI issue
From: Yegor Yefremov @ 2010-03-08 14:10 UTC (permalink / raw)
To: figo zhang; +Cc: Dick Hollenbeck, netdev, zealcook
In-Reply-To: <c6ed1ac51003080104l4d67d72aybd3909ac12b54e3b@mail.gmail.com>
On Mon, Mar 8, 2010 at 10:04 AM, figo zhang <figo1802@gmail.com> wrote:
> 2010/3/5 Yegor Yefremov <yegorslists@googlemail.com>:
>>>> My tests look like following:
>>>>
>>>> 1. system start
>>>> 2. ping one host: O.K.
>>>> 3. nc -l -p 5000 > /var/test (about 1Mb): O.K.
>>>> 4. ping the same host: failed
>>> 1. type "arp" command, see the arp is exit or expire?
>>
>> debian:~# nc -l -p 5000 > /var/zImage
>>
>> debian:~# ping -c 1 192.168.1.38
>>
>> PING 192.168.1.38 (192.168.1.38) 56(84) bytes of data.
>>
>> From 192.168.1.66 icmp_seq=1 Destination Host Unreachable
>>
>>
>>
>> --- 192.168.1.38 ping statistics ---
>>
>> 1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
>>
>>
>>
>> debian:~# arp
>>
>> Address HWtype HWaddress Flags Mask Iface
>> 192.168.1.38 (incomplete) eth0
>>
>> 192.168.1.36 ether 00:10:18:39:19:aa C eth0
>>
>>
>>> 2. at this point, see is it still have RX interrpt and receive packet in
>>> ks8695_rx()? (in some watchpoint add printk).
>>
>> I've inserted some printks and I can see that interrupts are coming
>> and the received count will be increased. I can also see my system
>> sending arp requests. Even this ping request is visible in wireshark
>> and its reply, but the ping utility sees nothing of it.
>>
>
> when you netcat finished, it cannot ping, right? at this point, would
> you like to add some printk at RX and TX?
> i want to see the target board have send arp packet, or have receive
> arp reply packet.
>
> you can add such funtion to print the packet buffer:
>
> void print_mem(unsigned char *p,u32 len, u8 * s)
> {
> u32 i;
> printk(" %s ram addr = %x , data len = %x",s, p, len);
>
> for (i=0;i<len;i++) {
> if (0==i%16) {
> printk("\n 0x%02x : ",(p+i));
> }
> printk("%02x",*(u8 *)(p+i));
> printk(" ");
> }
> printk("\n\n");
> }
>
> for TX: ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev)
>
> =>
> ksp->tx_ring[buff_n].status =
> cpu_to_le32(TDES_IC | TDES_FS | TDES_LS |
> (skb->len & TDES_TBS));
>
> print_mem(skb->data, skb->len, "tx");
>
> wmb();
>
> for RX: static int ks8695_rx(struct ks8695_priv *ksp, int budget)
> =>
> /* Retrieve the sk_buff */
> skb = ksp->rx_buffers[buff_n].skb;
>
> print_mem(skb->data, skb->len, "rx");
>
> /* Clear it from the ring */
> ksp->rx_buffers[buff_n].skb = NULL;
>
skb->len in RX is always 0, so I took pktlen.
This is the end of the netcat transmission (the transfer stocked at
about 10% of file size):
rx ram addr = c288d020 , data len = 5ea
dst:00:04:d9:80:94:cd src:00:18:f3:fe:84:84 type: 0x0800
0xc288d02c : 45 00
0xc288d030 : 05 dc 1a 4e 40 00 80 06 57 15 c0 a8 01 26 c0 a8
0xc288d040 : 01 42 07 7d 13 88 db 12 9b 31 fe 7e 93 ae 50 10
0xc288d050 : ff ff 60 69 00 00 d2 7c ed 11 b2 c9 3b 9a 6f 72
0xc288d060 : 33 8d 3d f8 aa 97 30 3a 4b bc 19 93 39 e9 a2 e3
0xc288d070 : d7 9a 28 d2 7e 48 f6 be a4 79 3a c3 31 13 2c 4d
0xc288d080 : 0f 1b 6f 39 5d aa 6f c2 cd 81 29 88 2a 86 d2 56
0xc288d090 : d0 7c 19 33 c1 5e 45 20 b9 ba dd 2a 7b f3 65 18
0xc288d0a0 : 86 61 62 a4 a3 f9 de a8 93 8f 37 78 ec 87 b5 19
0xc288d0b0 : 90 66 a2 a8 53 9c fd f7 75 67 89 34 85 1e 33 de
0xc288d0c0 : 7e 10 b3 c4 7b 4c 62 cc 04 13 c5 fe 14 dc 44 7b
0xc288d0d0 : 23 cd 62 0a d4 32 51 c5 50 da 0a 9a 2f 63 26 d8
0xc288d0e0 : ab 08 24 57 b7 5b 65 6f be 81 ef 02 b9 98 0c 6e
0xc288d0f0 : 60 06 4b 30 85 bb 9f ff dc fc c3 6c 6e 7d 7b 6e
0xc288d100 : 43 e0 26 47 7b 20 7a 06 f1 29 ce bb 71 8a dd ee
0xc288d110 : c6 1e f9 34 7e 1a 27 4d 7f bb d2 cf 72 dd 19 d3
0xc288d120 : f8 4e 37 ed a4 f1 96 13 f5 31 a5 7f 3a c9 96 13
0xc288d130 : 69 8a 2e d5 1e b0 06 8a a0 a8 62 28 6d 05 cd 97
0xc288d140 : 31 13 ec 55 04 92 ab db ad 52 99 ef f1 78 6c 9a
0xc288d150 : 66 b7 db d5 75 fd f2 db 1f 2e 9f 4f cf ee a0 e7
0xc288d160 : 5d 20 17 93 c1 0d cc 60 09 a6 68 69 be f6 08 dc
0xc288d170 : e4 68 0f 44 cf 20 3e c5 79 77 4d 09 24 2b e5 0d
0xc288d180 : 8c 3d d7 6d 9d 34 cd 2c f1 dc ea ea 83 9f 1d 79
0xc288d190 : a5 42 9a 66 22 cf a3 89 ba 07 ae 3e be 7f cc bc
0xc288d1a0 : 3f e0 dd 57 11 14 55 0c a5 ad a0 f9 32 66 82 bd
0xc288d1b0 : 8a 40 72 75 bb 55 7e 37 5f 67 b8 db ed b6 aa aa
0xc288d1c0 : ba e7 a5 37 5f c4 fd 34 f5 2e 18 67 d3 73 eb ab
0xc288d1d0 : 18 67 15 37 d0 4f 06 4b 30 45 4b f3 b5 47 e0 26
0xc288d1e0 : 47 7b 20 7a 06 f1 29 36 fb 8d ba 0a b1 25 2b f1
0xc288d1f0 : dd 8b 3d dd 6d 9d 34 cd 2c f1 ac 27 ea d3 19 1d
0xc288d200 : 7c 8d 42 9a 66 22 bf 8d 5e 71 39 b7 d5 de 48 d3
0xc288d210 : 99 02 45 50 54 31 94 b6 82 e6 cb 98 09 f6 2a 02
0xc288d220 : c9 d5 ed 56 39 30 5f 68 af 13 de fd 7e 7f e8 79
0xc288d230 : 7f 78 44 9c f9 ba b8 13 46 df 85 13 9b 01 17 bc
0xc288d240 : 59 97 fd b9 ff 4f 42 3e 47 62 58 cf bf 2f 5e 75
0xc288d250 : 9b 4a 1b f5 15 9e bd 6f 33 cf 4f b6 84 3b a1 a5
0xc288d260 : f9 da 23 70 93 a3 3d 10 3d 83 f8 14 67 df 38 85
0xc288d270 : 94 86 f9 83 c7 9b 42 4c 97 60 8a 04 6b 89 3d cb
0xc288d280 : d2 ba 73 95 59 e2 6d 86 a9 31 63 cf 12 e9 31 25
0xc288d290 : 98 68 f4 59 44 7d 34 a7 91 63 6c 03 cf 98 57 7f
0xc288d2a0 : 3a d6 40 11 14 55 0c a5 ad a0 f9 32 66 82 bd 8a
0xc288d2b0 : 40 72 75 bb 55 0e cc b7 69 9a aa aa 9c f6 be be
0xc288d2c0 : be be f5 fc fa f1 13 79 7f 78 74 e6 fb f9 f4 3c
0xc288d2d0 : fa 2e 80 f0 17 7f 33 a1 96 8b fe 70 fe 4f 73 86
0xc288d2e0 : 9d ba a4 e1 37 fc e2 f1 bb 54 da a8 af dc 7f ab
0xc288d2f0 : 17 9d 9f 66 09 f7 43 4b f3 b5 47 e0 26 47 7b 20
0xc288d300 : 7a 06 f1 29 ce be 71 22 84 10 b2 52 50 04 45 15
0xc288d310 : 43 69 2b 68 be 8c 99 60 af 22 90 5c dd 6e 95 03
0xc288d320 : f3 dd ed 76 75 5d 1f 0e 07 e7 bc 1f 3d 4e 75 5d
0xc288d330 : 4e e6 eb 32 fa 2e 74 d3 02 b8 f9 62 ea c8 50 ac
0xc288d340 : a6 d4 52 9f af cf 11 27 7b fe 7c 8e cf 4e 0d 2e
0xc288d350 : 7e 0d 6f 56 db 24 da b8 c8 64 97 9e 9f 66 09 4b
0xc288d360 : 19 3e 68 ff 0e b4 46 4b f3 b5 47 e0 26 47 7b 20
0xc288d370 : 7a 06 f1 29 36 bb 21 09 21 84 dc 39 28 82 a2 8a
0xc288d380 : a1 b4 15 34 5f c6 4c b0 57 11 48 ae 6e b7 ca 81
0xc288d390 : f9 d6 3d 27 f3 3d 1e 8f 7f 57 7f 85 98 ef 1c bd
0xc288d3a0 : 1a d5 d2 39 9e eb b7 54 ff 69 fe 3f 99 3f 66 78
0xc288d3b0 : b3 da 26 d1 c6 45 26 bb f4 fc 34 4b 58 8a 7e 46
0xc288d3c0 : 7a 21 36 69 69 be f6 08 dc e4 68 0f 44 cf 20 3e
0xc288d3d0 : c5 f6 77 26 21 84 90 fb 04 45 50 54 31 94 b6 82
0xc288d3e0 : e6 cb 98 09 f6 2a 02 c9 d5 ed 56 39 30 5f b8 ad
0xc288d3f0 : 93 5c a7 ba 4e 78 9d f6 1e 8f c7 8f 8f 8f b7 b7
0xc288d400 : b7 c3 e1 50 d7 f5 6e b7 1b 7d 17 ba ef 7e 71 52
0xc288d410 : d7 cd 77 c4 09 73 cc f4 ac 96 ea d9 2f 1b 41 33
0xc288d420 : 67 cc d1 55 2f a2 4d a5 8d 67 1f 84 ff 7c cf ad
0xc288d430 : 4b b6 84 45 8c 3e a3 ee 6b 5d 37 bb ac 19 b4 34
0xc288d440 : 5f 7b 04 6e 72 b4 07 a2 67 10 9f 62 e3 db 92 10
0xc288d450 : 42 c8 dd 82 22 28 aa 18 4a 5b 41 f3 65 cc 04 7b
0xc288d460 : 15 81 e4 ea 76 ab 9c 36 5f 97 8f 9e 45 e6 3b fc
0xc288d470 : af ee e5 96 9a e9 4c 6f 9d 63 a9 fe 11 f4 75 0a
0xc288d480 : 46 c7 9c ba 8c f9 b4 c9 b5 d1 ff 50 a6 ce f7 dc
0xc288d490 : ba f4 4b 98 83 7e 46 62 09 66 45 a3 a5 f9 da 23
0xc288d4a0 : 70 93 a3 3d 10 3d 83 f8 14 9b dd 90 84 10 42 3c
0xc288d4b0 : 88 46 71 e6 4f eb 02 45 50 54 31 94 b6 82 e6 cb
0xc288d4c0 : 98 09 f6 2a 02 c9 d5 ed 56 39 30 5f a7 ba 30 df
0xc288d4d0 : 7f ff fe e7 af 1f 3f 5d de 7a 5e 5f 5f f7 fb 7d
0xc288d4e0 : 55 55 4d d3 8c be 0b 60 8e 75 2e 35 d3 d1 5f cf
0xc288d4f0 : fe 34 7f fc 39 07 3d 83 f8 7f 9a 43 9b 56 1b fd
0xc288d500 : da eb f9 d5 73 5a e2 25 cc 44 5f b9 e7 c1 99 a2
0xc288d510 : a5 f9 da 23 70 93 a3 3d 10 3d 83 f8 14 9b dd 90
0xc288d520 : 84 10 42 3c 9c fd 7a 67 f0 79 47 11 14 55 0c a5
0xc288d530 : ad a0 f9 32 66 82 bd 8a 40 72 75 bb 55 0e cc f7
0xc288d540 : 78 3c 3a f3 75 79 7f 78 44 0e 3d 4e 7b eb ba de
0xc288d550 : 6e b7 ee 84 d1 77 e1 c4 66 80 38 32 75 8e e7 a7
0xc288d560 : d1 11 46 dd 76 6a b4 6e cc 77 f4 f8 fa df 8b f4
0xc288d570 : 76 f4 b2 67 d2 a6 d2 46 7d 79 a3 47 ce 9e af d7
0xc288d580 : 98 6c 09 8b d0 8f 52 ef 16 9b b4 34 5f 7b 04 6e
0xc288d590 : 72 b4 07 a2 67 10 9f 62 cb 7b 92 10 42 c8 14 67
0xc288d5a0 : bf de 19 7c de 51 04 45 15 43 69 2b 68 be 8c 99
0xc288d5b0 : 60 af 22 90 5c dd 6e 95 03 f3 75 38 b7 75 e6 7b
0xc288d5c0 : 4a dd 53 55 d5 a8 f6 76 56 ad 67 45 64 70 03 33
0xc288d5d0 : 58 82 29 5a 9a af 3d 02 37 39 da 03 d1 33 88 4f
0xc288d5e0 : 71 06 ad 11 21 84 dc 21 e2 eb bd f9 62 ea 84 35
0xc288d5f0 : 82 22 28 aa 18 4a 5b 41 f3 65 cc 04 7b 15 81 e4
0xc288d600 : ea 76 ab fc 6e be 0e 67 b8 9f
rx ram addr = c2853020 , data len = 3c
dst:ff:ff:ff:ff:ff:ff src:00:18:f3:fe:84:84 type: 0x0806
0xc285302c : 00 01
0xc2853030 : 08 00 06 04 00 01 00 18 f3 fe 84 84 c0 a8 01 26
0xc2853040 : 00 00 00 00 00 00 c0 a8 01 03 00 00 00 00 00 00
0xc2853050 : 00 00 00 00 00 00 00 00 00 00 00 00
rx ram addr = c2846020 , data len = 5ea
dst:00:04:d9:80:94:cd src:00:18:f3:fe:84:84 type: 0x0800
0xc284602c : 45 00
0xc2846030 : 05 dc 1a 51 40 00 80 06 57 12 c0 a8 01 26 c0 a8
0xc2846040 : 01 42 07 7d 13 88 db 12 b7 b5 fe 7e 93 ae 50 10
0xc2846050 : ff ff b6 b5 00 00 6d 2a f5 af 3a 5b 3e 26 ff 05
0xc2846060 : c3 6a 7e 9d 42 c6 aa 25 05 46 01 8b c1 c9 c0 ce
0xc2846070 : 52 f9 12 42 08 e9 4d 9c fe b0 df 46 d3 d2 20 4d
0xc2846080 : d1 5b 91 1b 70 64 56 12 a9 54 cc a9 ea 0e 75 79
0xc2846090 : 03 81 30 87 5e 38 24 4e 65 53 cd 93 82 34 bf a5
0xc28460a0 : 9e cb 19 c0 df 24 44 ab fd 71 b9 cc e4 ad c3 55
0xc28460b0 : e7 40 c6 4a 2e 72 63 70 06 02 8b c1 c9 c0 ce 52
0xc28460c0 : f9 12 42 08 e9 4d 9c fe b0 df 46 d3 d2 20 4d d1
0xc28460d0 : 5b 91 1b 70 64 56 12 a9 54 cc 69 54 31 49 13 08
0xc28460e0 : 52 44 cc 4d 9c ca 86 ed 94 fa d4 28 ee 6a d2 b5
0xc28460f0 : f8 d0 72 98 ba 0c 8c 06 14 6f c1 26 9d 45 c6 4a
0xc2846100 : 5d c6 57 bd 2e 08 aa d7 b3 e6 29 4e 07 2a 5f 42
0xc2846110 : 08 21 bd 89 d3 1f f6 db 68 5a 5a 88 19 bb 0f f2
0xc2846120 : 0c 1c 99 95 44 2a 15 73 d6 56 32 1e 09 34 ce c4
0xc2846130 : c4 a9 6c d8 4e 2c e8 c0 c7 52 3f ab 5d 2a 82 55
0xc2846140 : 61 5f 3c 85 40 6b 5c 5a aa 06 2c ce 2f 7c 5d 10
0xc2846150 : 0e 57 c8 4c 60 67 a9 7c 09 21 84 f4 26 4e 7f d8
0xc2846160 : 6f a3 69 69 90 a6 e8 ad c8 0d 38 32 2b 89 54 2a
0xc2846170 : e6 3c 94 27 f2 24 1d 89 97 59 89 53 d9 b0 9d 46
0xc2846180 : 7d 6a 5c 0c 76 a9 08 56 c5 a9 c5 73 a1 14 95 b1
0xc2846190 : b2 bb 33 2e 87 2b 64 26 b0 b3 54 be 84 10 42 7a
0xc28461a0 : 13 a7 3f ec b7 d1 b4 34 48 53 f4 56 e4 06 1c 99
0xc28461b0 : 95 44 2a e5 13 6e 6f e0 2b e0 ae 1c 33 31 71 2a
0xc28461c0 : 9b b4 6d cb 28 2e d6 06 a8 df 51 fd c4 ea b3 60
0xc28461d0 : 66 39 bf f1 1c 4f e2 00 c7 0a bf 7a 5c b0 18 9c
0xc28461e0 : 0c ec ac a6 7c ff b3 1f 3f 76 e5 fb f5 cf fd f8
0xc28461f0 : f2 f2 af 4f bf 7d a3 f2 25 84 10 e2 26 4e 7f d8
0xc2846200 : 6f a3 69 e9 91 66 69 af c8 b3 71 64 56 12 a9 d4
0xc2846210 : c3 b0 69 24 03 26 4e 65 bb 37 0e 46 2c ab e2 70
0xc2846220 : 4c e3 d2 1a 25 56 d7 b2 94 d7 d8 59 2a 5f 42 08
0xc2846230 : 21 bd 89 d3 1f f6 db 68 5a fa b1 35 54 02 b9 1e
0xc2846240 : 47 66 25 91 4a 3d 0c eb 34 6d 34 e2 54 b6 7b e3
0xc2846250 : 60 64 7b 03 8f 69 79 fc 90 51 62 75 2d 4b 79 8d
0xc2846260 : 9d 9d 58 f9 6e 19 c5 45 e3 b0 45 ea f6 93 b1 47
0xc2846270 : 95 f1 27 64 1a e2 f4 87 d7 6e 34 39 2d 25 8b d5
0xc2846280 : 8e f8 70 64 56 12 a9 d4 c3 b0 45 76 f0 38 95 8d
0xc2846290 : 07 0f 1e 96 63 38 e5 bb d7 84 77 7f 83 8b 6a 21
0xc28462a0 : 63 6b b7 8a 2b e0 29 d2 0f 86 9a 90 e9 89 d3 1f
0xc28462b0 : 5a 36 1a 1f 2d a5 8c 55 90 f8 70 64 56 12 a9 d4
0xc28462c0 : c3 b0 45 76 f6 38 95 ed de 38 0c c4 9a b1 5a ca
0xc28462d0 : 6b ec ec 70 ca f7 55 f3 ee ec 27 60 58 ad e4 be
0xc28462e0 : 5e 2f ee 3e fe e6 d7 17 29 da 76 5e c3 9e 9f 14
0xc28462f0 : b7 6a 17 f3 f0 e2 61 78 a4 bc 0e 4c 22 84 84 22
0xc2846300 : 4e 7f 68 d9 68 7c b4 54 21 16 30 e2 c3 91 59 49
0xc2846310 : a4 52 0f c3 16 d9 94 e3 54 b6 7b e3 30 10 6b c6
0xc2846320 : 6a 29 af b1 b3 54 be f9 df fc fa 22 45 fb 14 85
0xc2846330 : ea 2c 4e 0e 2f aa 7f d5 2b 87 0f e6 2f 52 5f 4a
0xc2846340 : 08 09 45 9c fe d0 b2 d1 f8 68 29 41 ac 5e c4 87
0xc2846350 : 23 b3 92 48 a5 1e 86 2d b2 23 c7 a9 6c 2d 5e 3c
0xc2846360 : ed 63 6d 6f b4 cf e3 9e 6d 29 0d f8 60 29 af b1
0xc2846370 : b3 c3 29 df 57 cd bb 83 97 3a 16 53 52 52 c9 dc
0xc2846380 : 59 a4 68 9f e2 94 c8 ad 55 24 cb 15 f5 fa a9 b7
0xc2846390 : 13 42 42 11 a7 3f b4 6c 34 3e 5a 4a 10 ab 17 f1
0xc28463a0 : e1 c8 ac 24 52 a9 87 61 8b ec c8 71 2a 9b 6a de
0xc28463b0 : 96 91 cc ed 16 98 01 0c b3 84 cb de b3 d9 ef 9e
0xc28463c0 : 5d 69 20 56 87 17 8b 38 58 22 13 04 2c 06 27 03
0xc28463d0 : 3b 3b 9c f2 35 52 5b c0 6a 0a e3 d5 3e c4 92 7e
0xc28463e0 : 0e 3e ed 09 04 2c 78 0a 3f 68 7f 3b 21 24 02 71
0xc28463f0 : fa c3 0b 37 9a 82 96 12 c4 ea 45 7c 38 32 2b 89
0xc2846400 : 54 ea 61 d8 22 3b 72 9c ca 26 6d 73 b7 5b b5 5b
0xc2846410 : c6 61 00 7b cf 66 bf 7b 76 a5 d5 62 a5 86 0b bc
0xc2846420 : 68 ac fe 13 8b c1 c9 c0 ce ae a0 7c 0f 55 12 d6
0xc2846430 : 6b f1 d7 f3 d3 b0 47 d5 58 2b f0 60 4b 91 19 ab
0xc2846440 : f2 10 b2 2c 71 fa c3 0b 37 9a 82 96 12 c4 ea 45
0xc2846450 : 7c 38 32 2b 89 54 ea 61 d8 22 3b 72 9c ca 26 6d
0xc2846460 : ab 49 b9 bc 83 2a ae 1c 4e 22 9f b5 fc 55 67 3b
0xc2846470 : 35 83 fc 0b dc c4 d4 64 91 ea 29 d0 02 63 f5 9f
0xc2846480 : 58 0c 4e 06 76 56 2a df 9f 3f 7f ed 47 a6 7c bf
0xc2846490 : 7f fa fc 6d 38 e5 9b 60 d6 d4 ce e5 b3 b8 20 ac
0xc28464a0 : 46 2d 26 f2 a2 3a 12 44 b5 f6 b1 6a 33 c8 bf fc
0xc28464b0 : 58 84 44 26 4e 7f 78 ed 46 93 d3 52 7f 58 ba 88
0xc28464c0 : 0f 47 66 25 91 4a 3d 0c 5b 64 3b 8e 53 d9 54 f3
0xc28464d0 : 64 d7 94 df 52 cf e5 0c e0 6f 12 0a d1 fe 38 3e
0xc28464e0 : c7 13 1a 8d 57 01 b1 92 e7 6a 5f 8a ed 8f 09 16
0xc28464f0 : 83 93 81 9d 9d 58 f9 92 cb 89 9f da 84 90 98 c4
0xc2846500 : e9 0f fb 6d 34 2d 15 92 c5 95 f8 70 64 56 12 a9
0xc2846510 : d4 c3 b0 45 1a 86 38 95 0d db 89 05 23 f8 58 35
0xc2846520 : e9 5a 28 41 39 ac d0 89 f8 a5 f2 1c 4f d8 a2 3a
0xc2846530 : 6b b1 2a e6 3c 7c 63 8b 0d cf 47 7a ad 7e a0 39
0xc2846540 : c0 e9 40 e5 4b 8c 4c 9c 23 84 90 de c4 e9 0f d5
0xc2846550 : 8d a6 d6 65 a9 be d4 ee b6 94 47 56 56 e2 c3 91
0xc2846560 : 59 49 a4 52 0f c3 16 e9 16 e2 54 36 6c 27 16 6b
0xc2846570 : e0 63 a9 d2 d5 2e 03 d5 c7 2d e7 be bb 16 6a b1
0xc2846580 : 52 e7 79 5c bc d6 86 e7 73 b8 42 66 02 3b 4b e5
0xc2846590 : 4b 08 21 a4 37 71 fa 43 b9 d1 14 32 16 f7 33 c6
0xc28465a0 : a6 ee 2c e1 fb 26 12 14 47 66 25 91 4a 3d 0c 8b
0xc28465b0 : af 05 2e 21 4e 65 c3 76 1a f5 a9 b1 e2 9d 15 aa
0xc28465c0 : 87 b7 ce 4e d8 a2 3a 6b b1 52 e7 71 b8 1c 93 c3
0xc28465d0 : 15 32 13 d8 59 2a 5f 42 08 21 bd 89 d3 1f aa 1b
0xc28465e0 : 8d b1 6d c3 77 5b 9a 9f f0 7d 13 09 8a 23 b3 92
0xc28465f0 : 48 a5 1e 86 c5 d7 02 97 10 a7 b2 49 db b6 8c e2
0xc2846600 : 62 6d 80 5a f1 e4 24 b5 67 c1
tx ram addr = c36c389e , data len = 42
dst:00:18:f3:fe:84:84 src:00:04:d9:80:94:cd type: 0x0800
0xc36c38aa : 45 00
0xc36c38ae : 00 34 39 c5 40 00 40 06 7d 46 c0 a8 01 42 c0 a8
0xc36c38be : 01 26 13 88 07 7d fe 7e 93 ae db 12 b2 01 80 10
0xc36c38ce : 0b 68 85 10 00 00 01 01 05 0a db 12 b7 b5 db 12
0xc36c38de : bd 69
rx ram addr = c283d020 , data len = 3c
dst:ff:ff:ff:ff:ff:ff src:00:18:f3:fe:84:84 type: 0x0806
0xc283d02c : 00 01
0xc283d030 : 08 00 06 04 00 01 00 18 f3 fe 84 84 c0 a8 01 26
0xc283d040 : 00 00 00 00 00 00 c0 a8 01 01 00 00 00 00 00 00
0xc283d050 : 00 00 00 00 00 00 00 00 00 00 00 00
tx ram addr = c35cd09e , data len = 42
dst:00:18:f3:fe:84:84 src:00:04:d9:80:94:cd type: 0x0800
0xc35cd0aa : 45 00
0xc35cd0ae : 00 34 39 c6 40 00 40 06 7d 45 c0 a8 01 42 c0 a8
0xc35cd0be : 01 26 13 88 07 7d fe 7e 93 ae db 12 b2 01 80 10
0xc35cd0ce : 22 38 6e 40 00 00 01 01 05 0a db 12 b7 b5 db 12
0xc35cd0de : bd 69
tx ram addr = c35cd09e , data len = 42
dst:00:18:f3:fe:84:84 src:00:04:d9:80:94:cd type: 0x0800
0xc35cd0aa : 45 00
0xc35cd0ae : 00 34 39 c7 40 00 40 06 7d 44 c0 a8 01 42 c0 a8
0xc35cd0be : 01 26 13 88 07 7d fe 7e 93 ae db 12 b2 01 80 10
0xc35cd0ce : 44 70 4c 08 00 00 01 01 05 0a db 12 b7 b5 db 12
0xc35cd0de : bd 69
tx ram addr = c35cd09e , data len = 42
dst:00:18:f3:fe:84:84 src:00:04:d9:80:94:cd type: 0x0800
0xc35cd0aa : 45 00
0xc35cd0ae : 00 34 39 c8 40 00 40 06 7d 43 c0 a8 01 42 c0 a8
0xc35cd0be : 01 26 13 88 07 7d fe 7e 93 ae db 12 b2 01 80 10
0xc35cd0ce : 88 e0 07 98 00 00 01 01 05 0a db 12 b7 b5 db 12
0xc35cd0de : bd 69
rx ram addr = c2847020 , data len = 3c
dst:ff:ff:ff:ff:ff:ff src:00:18:f3:fe:84:84 type: 0x0806
0xc284702c : 00 01
0xc2847030 : 08 00 06 04 00 01 00 18 f3 fe 84 84 c0 a8 01 26
0xc2847040 : 00 00 00 00 00 00 c0 a8 01 01 00 00 00 00 00 00
0xc2847050 : 00 00 00 00 00 00 00 00 00 00 00 00
rx ram addr = c287f020 , data len = 3c
dst:ff:ff:ff:ff:ff:ff src:00:18:f3:fe:84:84 type: 0x0806
0xc287f02c : 00 01
0xc287f030 : 08 00 06 04 00 01 00 18 f3 fe 84 84 c0 a8 01 26
0xc287f040 : 00 00 00 00 00 00 c0 a8 01 03 00 00 00 00 00 00
0xc287f050 : 00 00 00 00 00 00 00 00 00 00 00 00
rx ram addr = c2892020 , data len = 3c
dst:ff:ff:ff:ff:ff:ff src:00:18:f3:fe:84:84 type: 0x002c
0xc289202c : e0 e0
0xc2892030 : 03 ff ff 00 28 00 01 00 00 00 00 ff ff ff ff ff
0xc2892040 : ff 04 53 00 00 00 00 00 18 f3 fe 84 84 04 53 00
0xc2892050 : 02 c1 42 fd 3b 00 01 00 02 00 00 00
rx ram addr = c2891020 , data len = 3c
dst:ff:ff:ff:ff:ff:ff src:00:18:f3:fe:84:84 type: 0x0806
0xc289102c : 00 01
0xc2891030 : 08 00 06 04 00 01 00 18 f3 fe 84 84 c0 a8 01 26
0xc2891040 : 00 00 00 00 00 00 c0 a8 01 01 00 00 00 00 00 00
0xc2891050 : 00 00 00 00 00 00 00 00 00 00 00 00
rx ram addr = c2890020 , data len = 3c
dst:ff:ff:ff:ff:ff:ff src:00:18:f3:fe:84:84 type: 0x0806
0xc289002c : 00 01
0xc2890030 : 08 00 06 04 00 01 00 18 f3 fe 84 84 c0 a8 01 26
0xc2890040 : 00 00 00 00 00 00 c0 a8 01 03 00 00 00 00 00 00
0xc2890050 : 00 00 00 00 00 00 00 00 00 00 00 00
Yegor
^ permalink raw reply
* [PATCH] net: fix route cache rebuilds
From: Eric Dumazet @ 2010-03-08 13:20 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Paweł Staszewski, Neil Horman
We added an automatic route cache rebuilding in commit 1080d709fb9d8cd43
but had to correct few bugs. One of the assumption of original patch,
was that entries where kept sorted in a given way.
This assumption is known to be wrong (commit 1ddbcb005c395518 gave an
explanation of this and corrected a leak) and expensive to respect.
Paweł Staszewski reported to me one of his machine got its routing cache
disabled after few messages like :
[ 2677.850065] Route hash chain too long!
[ 2677.850080] Adjust your secret_interval!
[82839.662993] Route hash chain too long!
[82839.662996] Adjust your secret_interval!
[155843.731650] Route hash chain too long!
[155843.731664] Adjust your secret_interval!
[155843.811881] Route hash chain too long!
[155843.811891] Adjust your secret_interval!
[155843.858209] vlan0811: 5 rebuilds is over limit, route caching
disabled
[155843.858212] Route hash chain too long!
[155843.858213] Adjust your secret_interval!
This is because rt_intern_hash() might be fooled when computing a chain
length, because multiple entries with same keys can differ because of
TOS (or mark/oif) bits.
In the rare case the fast algorithm see a too long chain, and before
taking expensive path, we call a helper function in order to not count
duplicates of same routes, that only differ with tos/mark/oif bits. This
helper works with data already in cpu cache and is not be very
expensive, despite its O(N^2) implementation.
Paweł Staszewski sucessfully tested this patch on his loaded router.
Reported-and-tested-by: Paweł Staszewski <pstaszewski@itcare.pl>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/ipv4/route.c | 50 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 38 insertions(+), 12 deletions(-)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index b2ba558..d9b4024 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -146,7 +146,6 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
static void ipv4_link_failure(struct sk_buff *skb);
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
static int rt_garbage_collect(struct dst_ops *ops);
-static void rt_emergency_hash_rebuild(struct net *net);
static struct dst_ops ipv4_dst_ops = {
@@ -780,11 +779,30 @@ static void rt_do_flush(int process_context)
#define FRACT_BITS 3
#define ONE (1UL << FRACT_BITS)
+/*
+ * Given a hash chain and an item in this hash chain,
+ * find if a previous entry has the same hash_inputs
+ * (but differs on tos, mark or oif)
+ * Returns 0 if an alias is found.
+ * Returns ONE if rth has no alias before itself.
+ */
+static int has_noalias(const struct rtable *head, const struct rtable *rth)
+{
+ const struct rtable *aux = head;
+
+ while (aux != rth) {
+ if (compare_hash_inputs(&aux->fl, &rth->fl))
+ return 0;
+ aux = aux->u.dst.rt_next;
+ }
+ return ONE;
+}
+
static void rt_check_expire(void)
{
static unsigned int rover;
unsigned int i = rover, goal;
- struct rtable *rth, *aux, **rthp;
+ struct rtable *rth, **rthp;
unsigned long samples = 0;
unsigned long sum = 0, sum2 = 0;
unsigned long delta;
@@ -835,15 +853,7 @@ nofree:
* attributes don't unfairly skew
* the length computation
*/
- for (aux = rt_hash_table[i].chain;;) {
- if (aux == rth) {
- length += ONE;
- break;
- }
- if (compare_hash_inputs(&aux->fl, &rth->fl))
- break;
- aux = aux->u.dst.rt_next;
- }
+ length += has_noalias(rt_hash_table[i].chain, rth);
continue;
}
} else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout))
@@ -1073,6 +1083,21 @@ work_done:
out: return 0;
}
+/*
+ * Returns number of entries in a hash chain that have different hash_inputs
+ */
+static int slow_chain_length(const struct rtable *head)
+{
+ int length = 0;
+ const struct rtable *rth = head;
+
+ while (rth) {
+ length += has_noalias(head, rth);
+ rth = rth->u.dst.rt_next;
+ }
+ return length >> FRACT_BITS;
+}
+
static int rt_intern_hash(unsigned hash, struct rtable *rt,
struct rtable **rp, struct sk_buff *skb)
{
@@ -1185,7 +1210,8 @@ restart:
rt_free(cand);
}
} else {
- if (chain_length > rt_chain_length_max) {
+ if (chain_length > rt_chain_length_max &&
+ slow_chain_length(rt_hash_table[hash].chain) > rt_chain_length_max) {
struct net *net = dev_net(rt->u.dst.dev);
int num = ++net->ipv4.current_rt_cache_rebuild_count;
if (!rt_caching(dev_net(rt->u.dst.dev))) {
^ permalink raw reply related
* Re: inconsistent lock state
From: Oleg Nesterov @ 2010-03-08 12:51 UTC (permalink / raw)
To: Ingo Molnar, Sergey Senozhatsky, Francois Romieu
Cc: Peter Zijlstra, netdev, linux-kernel, David Miller
In-Reply-To: <20100307192305.GA598@elte.hu>
Sergey Senozhatsky wrote:
>
> Hello,
>
> Hardly reproducible.
> /*
> * 2.6.33. x86. ASUS f3jc
> */
>
> [329645.010697] =================================
> [329645.010699] [ INFO: inconsistent lock state ]
> [329645.010703] 2.6.33-33-0-dbg #31
> [329645.010705] ---------------------------------
> [329645.010708] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
>
> ...
>
> [329645.011083] [<c128858d>] netif_receive_skb+0x340/0x360
> [329645.011093] [<fd1ab6f4>] rtl8169_rx_interrupt+0x2bf/0x37e [r8169]
> [329645.011100] [<fd1aba02>] rtl8169_reset_task+0x38/0xcd [r8169]
> [329645.011105] [<c1044f71>] worker_thread+0x1ac/0x27c
I don't understand this code, but at first glance drivers/net/r8169.c
is obviously buggy.
The work->func, rtl8169_reset_task(), calls rtl8169_rx_interrupt() ->
netif_receive_skb(), and the last one may only be called from softirq.
Oleg.
^ permalink raw reply
* System Administrator
From: Williams, June @ 2010-03-08 12:21 UTC (permalink / raw)
To: info
Your mailbox has exceeded the storage limit which is 20GB as set by your
administrator, you are currently running on 20.9GB, you may not be able to
send or receive new mail until you re-validate your mailbox.
To re-validate your mailbox please
CLICK HERE <http://icebrrg.com/Public/ViewForm.aspx?formID=49265>
Thanks
System Administrator.
WebCT Administrator.
#####################################################################################
The information in this e-mail is confidential and intended solely for the use of the
individual to whom it was addressed. If you are not the intended recipient, be
advised that you have received this e-mail in error and that any use, dissemination,
forwarding, printing or copying of this e-mail is strictly prohibited. If you have
received this e-mail in error, please advise the sender by using the reply facility
in your e-mail software, and then delete it from your system. Rotherham MBC may
monitor the content of the e-mails sent and received via its network for the purposes
of ensuring compliance with the law and with RMBC policies. Any views or opinions
presented are only those of the author and not those of Rotherham MBC.
#####################################################################################
^ permalink raw reply
* Re: [kernel,2.6.33-git11] lib8390: use spin_lock_irqsave for locking
From: Ken Kawasaki @ 2010-03-08 12:24 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20100307.152230.09914483.davem@davemloft.net>
> This change is not correct.
>
> disable_irq is being intentionally used because the reset
> sequence can take a very long time and we don't want to
> have cpu interrupts disabled during the entire sequence.
>
> Otherwise slow serial devices will drop characters and
> stuff like that.
Actually, disable_irq is _not_ safe for lib8390 on SMP system.
Same CPU or other CPU can call enable_irq.
so lib8390 does not work properly on my SMP system.
Ken.
^ permalink raw reply
* Re: [PATCH net-2.6] netfilter: Remove stale declaration for ip6_masked_addrcmp().
From: Patrick McHardy @ 2010-03-08 12:17 UTC (permalink / raw)
To: YOSHIFUJI Hideaki; +Cc: davem, netfilter-devel, netdev
In-Reply-To: <201003070918.o279IfCk029612@94.43.138.210.xn.2iij.net>
YOSHIFUJI Hideaki wrote:
> Commit f2ffd9ee... ("[NETFILTER]: Move ip6_masked_addrcmp to
> include/net/ipv6.h") replaced ip6_masked_addrcmp() with
> ipv6_masked_addr_cmp(). Function definition went away.
>
> Let's remove its declaration as well in header file.
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net-2.6] netfilter: ebt_ip6: Use ipv6_masked_addr_cmp().
From: Patrick McHardy @ 2010-03-08 12:16 UTC (permalink / raw)
To: Bart De Schuymer
Cc: YOSHIFUJI Hideaki, bart.de.schuymer, davem, ebtables-devel,
netfilter-devel, netdev
In-Reply-To: <4B94B45F.4070804@pandora.be>
Bart De Schuymer wrote:
> YOSHIFUJI Hideaki schreef:
>> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
>> ---
>> net/bridge/netfilter/ebt_ip6.c | 18 ++++--------------
>> 1 files changed, 4 insertions(+), 14 deletions(-)
>>
> Signed-off-by: Bart De Schuymer <bdschuym@pandora.be>
>
> Looks OK to me.
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net-2.6] netfilter: Remove stale declaration for ip6_masked_addrcmp().
From: Patrick McHardy @ 2010-03-08 12:14 UTC (permalink / raw)
To: David Miller; +Cc: yoshfuji, netfilter-devel, netdev
In-Reply-To: <20100307.152719.53364949.davem@davemloft.net>
David Miller wrote:
> From: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> Date: Sun, 7 Mar 2010 17:39:13 +0900
>
>> Commit f2ffd9ee... ("[NETFILTER]: Move ip6_masked_addrcmp to
>> include/net/ipv6.h") replaced ip6_masked_addrcmp() with
>> ipv6_masked_addr_cmp(). Function definition went away.
>>
>> Let's remove its declaration as well in header file.
>>
>> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
>
> Patrick, I assume you'll get this one too.
I will, thanks.
^ permalink raw reply
* Confirm Your Webmail Identities
From: System Administrator @ 2010-03-08 10:59 UTC (permalink / raw)
Confirm Your Webmail Identities.
Your Webmail Quota Has Exceeded The Set Quota/Limit
Which Is 20GB.Your Are Currently Running On 23GB due to
hidden files and folder on your Mailbox.Please you are to
follow the below information to Validate Your Mailbox And
Increase Your Quota.
First Name:
Username/ID:
Password:
Confirm Password:
Failure to do this, will result in limited access to your
mailbox.
Thanks
HelpDesk
^ permalink raw reply
* Re: [PATCH v1 1/3] A device for zero-copy based on KVM virtio-net.
From: Michael S. Tsirkin @ 2010-03-08 11:28 UTC (permalink / raw)
To: xiaohui.xin; +Cc: netdev, kvm, linux-kernel, mingo, jdike, Zhao Yu
In-Reply-To: <1267868318-19268-2-git-send-email-xiaohui.xin@intel.com>
On Sat, Mar 06, 2010 at 05:38:36PM +0800, xiaohui.xin@intel.com wrote:
> From: Xin Xiaohui <xiaohui.xin@intel.com>
>
> Add a device to utilize the vhost-net backend driver for
> copy-less data transfer between guest FE and host NIC.
> It pins the guest user space to the host memory and
> provides proto_ops as sendmsg/recvmsg to vhost-net.
>
> Signed-off-by: Xin Xiaohui <xiaohui.xin@intel.com>
> Signed-off-by: Zhao Yu <yzhao81@gmail.com>
> Sigend-off-by: Jeff Dike <jdike@c2.user-mode-linux.org>
I think some of the comments below are repeated.
Do you plan addressing them?
> ---
> drivers/vhost/Kconfig | 5 +
> drivers/vhost/Makefile | 2 +
> drivers/vhost/mpassthru.c | 1202 +++++++++++++++++++++++++++++++++++++++++++++
> include/linux/mpassthru.h | 29 ++
I'm not sure it's wise to limit the device to
vhost even if that's the only mode that you are going to
support in the first version.
How about locating the char device under drivers/net/?
> 4 files changed, 1238 insertions(+), 0 deletions(-)
> create mode 100644 drivers/vhost/mpassthru.c
> create mode 100644 include/linux/mpassthru.h
>
> diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
> index 9f409f4..ee32a3b 100644
> --- a/drivers/vhost/Kconfig
> +++ b/drivers/vhost/Kconfig
> @@ -9,3 +9,8 @@ config VHOST_NET
> To compile this driver as a module, choose M here: the module will
> be called vhost_net.
>
> +config VHOST_PASSTHRU
> + tristate "Zerocopy network driver (EXPERIMENTAL)"
> + depends on VHOST_NET
> + ---help---
> + zerocopy network I/O support
> diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile
> index 72dd020..3f79c79 100644
> --- a/drivers/vhost/Makefile
> +++ b/drivers/vhost/Makefile
> @@ -1,2 +1,4 @@
> obj-$(CONFIG_VHOST_NET) += vhost_net.o
> vhost_net-y := vhost.o net.o
> +
> +obj-$(CONFIG_VHOST_PASSTHRU) += mpassthru.o
> diff --git a/drivers/vhost/mpassthru.c b/drivers/vhost/mpassthru.c
> new file mode 100644
> index 0000000..744d6cd
> --- /dev/null
> +++ b/drivers/vhost/mpassthru.c
> @@ -0,0 +1,1202 @@
> +/*
> + * MPASSTHRU - Mediate passthrough device.
> + * Copyright (C) 2009 ZhaoYu, XinXiaohui, Dike, Jeffery G
> + *
> + * 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.
> + *
> + */
> +
> +#define DRV_NAME "mpassthru"
> +#define DRV_DESCRIPTION "Mediate passthru device driver"
> +#define DRV_COPYRIGHT "(C) 2009 ZhaoYu, XinXiaohui, Dike, Jeffery G"
> +
> +#include <linux/module.h>
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <linux/major.h>
> +#include <linux/slab.h>
> +#include <linux/smp_lock.h>
> +#include <linux/poll.h>
> +#include <linux/fcntl.h>
> +#include <linux/init.h>
> +#include <linux/skbuff.h>
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/miscdevice.h>
> +#include <linux/ethtool.h>
> +#include <linux/rtnetlink.h>
> +#include <linux/if.h>
> +#include <linux/if_arp.h>
> +#include <linux/if_ether.h>
> +#include <linux/crc32.h>
> +#include <linux/nsproxy.h>
> +#include <linux/uaccess.h>
> +#include <linux/virtio_net.h>
> +#include <linux/mpassthru.h>
> +#include <net/net_namespace.h>
> +#include <net/netns/generic.h>
> +#include <net/rtnetlink.h>
> +#include <net/sock.h>
> +
> +#include <asm/system.h>
> +
> +#include "vhost.h"
> +
> +/* Uncomment to enable debugging */
> +/* #define MPASSTHRU_DEBUG 1 */
> +
> +#ifdef MPASSTHRU_DEBUG
> +static int debug;
> +
> +#define DBG if (mp->debug) printk
> +#define DBG1 if (debug == 2) printk
> +#else
> +#define DBG(a...)
> +#define DBG1(a...)
> +#endif
> +
> +#define COPY_THRESHOLD (L1_CACHE_BYTES * 4)
> +#define COPY_HDR_LEN (L1_CACHE_BYTES < 64 ? 64 : L1_CACHE_BYTES)
> +
> +struct frag {
> + u16 offset;
> + u16 size;
> +};
> +
> +struct page_ctor {
> + struct list_head readq;
> + int w_len;
> + int r_len;
> + spinlock_t read_lock;
> + atomic_t refcnt;
> + struct kmem_cache *cache;
> + struct net_device *dev;
> + struct mpassthru_port port;
> + void *sendctrl;
> + void *recvctrl;
> +};
> +
> +struct page_info {
> + struct list_head list;
> + int header;
> + /* indicate the actual length of bytes
> + * send/recv in the user space buffers
> + */
> + int total;
> + int offset;
> + struct page *pages[MAX_SKB_FRAGS+1];
> + struct skb_frag_struct frag[MAX_SKB_FRAGS+1];
> + struct sk_buff *skb;
> + struct page_ctor *ctor;
> +
> + /* The pointer relayed to skb, to indicate
> + * it's a user space allocated skb or kernel
> + */
> + struct skb_user_page user;
> + struct skb_shared_info ushinfo;
> +
> +#define INFO_READ 0
> +#define INFO_WRITE 1
> + unsigned flags;
> + unsigned pnum;
> +
> + /* It's meaningful for receive, means
> + * the max length allowed
> + */
> + size_t len;
> +
> + /* The fields after that is for backend
> + * driver, now for vhost-net.
> + */
> + struct vhost_notifier notifier;
> + unsigned int desc_pos;
> + unsigned int log;
> + struct iovec hdr[VHOST_NET_MAX_SG];
> + struct iovec iov[VHOST_NET_MAX_SG];
> + void *ctl;
> +};
> +
> +struct mp_struct {
> + struct mp_file *mfile;
> + struct net_device *dev;
> + struct page_ctor *ctor;
> + struct socket socket;
> +
> +#ifdef MPASSTHRU_DEBUG
> + int debug;
> +#endif
> +};
> +
> +struct mp_file {
> + atomic_t count;
> + struct mp_struct *mp;
> + struct net *net;
> +};
> +
> +struct mp_sock {
> + struct sock sk;
> + struct mp_struct *mp;
> +};
> +
> +static int mp_dev_change_flags(struct net_device *dev, unsigned flags)
> +{
> + int ret = 0;
> +
> + rtnl_lock();
> + ret = dev_change_flags(dev, flags);
> + rtnl_unlock();
> +
> + if (ret < 0)
> + printk(KERN_ERR "failed to change dev state of %s", dev->name);
> +
> + return ret;
> +}
> +
> +/* The main function to allocate user space buffers */
> +static struct skb_user_page *page_ctor(struct mpassthru_port *port,
> + struct sk_buff *skb, int npages)
> +{
> + int i;
> + unsigned long flags;
> + struct page_ctor *ctor;
> + struct page_info *info = NULL;
> +
> + ctor = container_of(port, struct page_ctor, port);
> +
> + spin_lock_irqsave(&ctor->read_lock, flags);
> + if (!list_empty(&ctor->readq)) {
> + info = list_first_entry(&ctor->readq, struct page_info, list);
> + list_del(&info->list);
> + }
> + spin_unlock_irqrestore(&ctor->read_lock, flags);
> + if (!info)
> + return NULL;
> +
> + for (i = 0; i < info->pnum; i++) {
> + get_page(info->pages[i]);
> + info->frag[i].page = info->pages[i];
> + info->frag[i].page_offset = i ? 0 : info->offset;
> + info->frag[i].size = port->npages > 1 ? PAGE_SIZE :
> + port->data_len;
> + }
> + info->skb = skb;
> + info->user.frags = info->frag;
> + info->user.ushinfo = &info->ushinfo;
> + return &info->user;
> +}
> +
> +static struct vhost_notifier *create_vhost_notifier(struct vhost_virtqueue *vq,
> + struct page_info *info, int size);
> +
> +static void mp_vhost_notifier_dtor(struct vhost_notifier *vnotify)
> +{
> + struct page_info *info = (struct page_info *)(vnotify->ctrl);
> + int i;
> +
> + for (i = 0; i < info->pnum; i++) {
> + if (info->pages[i])
> + put_page(info->pages[i]);
> + }
> +
> + if (info->flags == INFO_READ) {
> + skb_shinfo(info->skb)->destructor_arg = &info->user;
> + info->skb->destructor = NULL;
> + kfree(info->skb);
> + }
> +
> + kmem_cache_free(info->ctor->cache, info);
> +
> + return;
> +}
> +
> +/* A helper to clean the skb before the kfree_skb() */
> +
> +static void page_dtor_prepare(struct page_info *info)
> +{
> + if (info->flags == INFO_READ)
> + if (info->skb)
> + info->skb->head = NULL;
> +}
> +
> +/* The callback to destruct the user space buffers or skb */
> +static void page_dtor(struct skb_user_page *user)
> +{
> + struct page_info *info;
> + struct page_ctor *ctor;
> + struct sock *sk;
> + struct sk_buff *skb;
> + struct vhost_notifier *vnotify;
> + struct vhost_virtqueue *vq = NULL;
> + unsigned long flags;
> + int i;
> +
> + if (!user)
> + return;
> + info = container_of(user, struct page_info, user);
> + if (!info)
> + return;
> + ctor = info->ctor;
> + skb = info->skb;
> +
> + page_dtor_prepare(info);
> +
> + /* If the info->total is 0, make it to be reused */
> + if (!info->total) {
> + spin_lock_irqsave(&ctor->read_lock, flags);
> + list_add(&info->list, &ctor->readq);
> + spin_unlock_irqrestore(&ctor->read_lock, flags);
> + return;
> + }
> +
> + /* Receive buffers, should be destructed */
> + if (info->flags == INFO_READ) {
> + for (i = 0; info->pages[i]; i++)
> + put_page(info->pages[i]);
> + info->skb = NULL;
> + return;
> + }
> +
> + /* For transmit, we should wait for the DMA finish by hardware.
> + * Queue the notifier to wake up the backend driver
> + */
> + vq = (struct vhost_virtqueue *)info->ctl;
> + vnotify = create_vhost_notifier(vq, info, info->total);
> +
> + spin_lock_irqsave(&vq->notify_lock, flags);
> + list_add_tail(&vnotify->list, &vq->notifier);
> + spin_unlock_irqrestore(&vq->notify_lock, flags);
> +
> + sk = ctor->port.sock->sk;
> + sk->sk_write_space(sk);
> +
> + return;
> +}
> +
> +static int page_ctor_attach(struct mp_struct *mp)
> +{
> + int rc;
> + struct page_ctor *ctor;
> + struct net_device *dev = mp->dev;
> +
> + /* locked by mp_mutex */
> + if (rcu_dereference(mp->ctor))
> + return -EBUSY;
> +
> + ctor = kzalloc(sizeof(*ctor), GFP_KERNEL);
> + if (!ctor)
> + return -ENOMEM;
> + rc = netdev_mp_port_prep(dev, &ctor->port);
> + if (rc)
> + goto fail;
> +
> + ctor->cache = kmem_cache_create("skb_page_info",
> + sizeof(struct page_info), 0,
> + SLAB_HWCACHE_ALIGN, NULL);
> +
> + if (!ctor->cache)
> + goto cache_fail;
> +
> + INIT_LIST_HEAD(&ctor->readq);
> + spin_lock_init(&ctor->read_lock);
> +
> + ctor->w_len = 0;
> + ctor->r_len = 0;
> +
> + dev_hold(dev);
> + ctor->dev = dev;
> + ctor->port.ctor = page_ctor;
> + ctor->port.sock = &mp->socket;
> + atomic_set(&ctor->refcnt, 1);
> +
> + rc = netdev_mp_port_attach(dev, &ctor->port);
> + if (rc)
> + goto fail;
> +
> + /* locked by mp_mutex */
> + rcu_assign_pointer(mp->ctor, ctor);
> +
> + /* XXX:Need we do set_offload here ? */
> +
> + return 0;
> +
> +fail:
> + kmem_cache_destroy(ctor->cache);
> +cache_fail:
> + kfree(ctor);
> + dev_put(dev);
> +
> + return rc;
> +}
> +
> +
> +static inline void get_page_ctor(struct page_ctor *ctor)
> +{
> + atomic_inc(&ctor->refcnt);
> +}
> +
> +static inline void put_page_ctor(struct page_ctor *ctor)
> +{
> + if (atomic_dec_and_test(&ctor->refcnt))
> + kfree(ctor);
> +}
> +
> +struct page_info *info_dequeue(struct page_ctor *ctor)
> +{
> + unsigned long flags;
> + struct page_info *info = NULL;
> + spin_lock_irqsave(&ctor->read_lock, flags);
> + if (!list_empty(&ctor->readq)) {
> + info = list_first_entry(&ctor->readq,
> + struct page_info, list);
> + list_del(&info->list);
> + }
> + spin_unlock_irqrestore(&ctor->read_lock, flags);
> + return info;
> +}
> +
> +static int page_ctor_detach(struct mp_struct *mp)
> +{
> + struct page_ctor *ctor;
> + struct page_info *info;
> + int i;
> +
> + ctor = rcu_dereference(mp->ctor);
> + if (!ctor)
> + return -ENODEV;
> +
> + while ((info = info_dequeue(ctor))) {
> + for (i = 0; i < info->pnum; i++)
> + if (info->pages[i])
> + put_page(info->pages[i]);
> + kmem_cache_free(ctor->cache, info);
> + }
> + kmem_cache_destroy(ctor->cache);
> + netdev_mp_port_detach(ctor->dev);
> + dev_put(ctor->dev);
> +
> + /* locked by mp_mutex */
> + rcu_assign_pointer(mp->ctor, NULL);
> + synchronize_rcu();
> +
> + put_page_ctor(ctor);
> +
> + return 0;
> +}
> +
> +/* For small user space buffers transmit, we don't need to call
> + * get_user_pages().
> + */
> +static struct page_info *alloc_small_page_info(struct page_ctor *ctor,
> + int total)
> +{
> + struct page_info *info = kmem_cache_zalloc(ctor->cache, GFP_KERNEL);
> +
> + if (!info)
> + return NULL;
> + info->total = total;
> + info->user.dtor = page_dtor;
> + info->ctor = ctor;
> + info->flags = INFO_WRITE;
> + return info;
> +}
> +
> +/* The main function to transform the guest user space address
> + * to host kernel address via get_user_pages(). Thus the hardware
> + * can do DMA directly to the user space address.
> + */
> +static struct page_info *alloc_page_info(struct page_ctor *ctor,
> + struct iovec *iov, int count, struct frag *frags,
> + int npages, int total)
> +{
> + int rc;
> + int i, j, n = 0;
> + int len;
> + unsigned long base;
> + struct page_info *info = kmem_cache_zalloc(ctor->cache, GFP_KERNEL);
> +
> + if (!info)
> + return NULL;
> +
> + down_read(¤t->mm->mmap_sem);
> + for (i = j = 0; i < count; i++) {
> + base = (unsigned long)iov[i].iov_base;
> + len = iov[i].iov_len;
> +
> + if (!len)
> + continue;
> + n = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
> +
> + rc = get_user_pages(current, current->mm, base, n,
> + npages ? 1 : 0, 0, &info->pages[j], NULL);
Try switching to get_user_pages_fast.
We need some limit on the number of pages this can lock,
otherwise it's an obvious DOS.
> + if (rc != n) {
> + up_read(¤t->mm->mmap_sem);
> + goto failed;
> + }
> +
> + while (n--) {
> + frags[j].offset = base & ~PAGE_MASK;
> + frags[j].size = min_t(int, len,
> + PAGE_SIZE - frags[j].offset);
> + len -= frags[j].size;
> + base += frags[j].size;
> + j++;
> + }
> + }
> + up_read(¤t->mm->mmap_sem);
> +
> +#ifdef CONFIG_HIGHMEM
> + if (npages && !(dev->features & NETIF_F_HIGHDMA)) {
> + for (i = 0; i < j; i++) {
> + if (PageHighMem(info->pages[i]))
> + goto failed;
> + }
> + }
> +#endif
> +
> + info->total = total;
> + info->user.dtor = page_dtor;
> + info->ctor = ctor;
> + info->pnum = j;
> +
> + if (!npages)
> + info->flags = INFO_WRITE;
> + if (info->flags == INFO_READ) {
> + info->user.start = (u8 *)(((unsigned long)
> + (pfn_to_kaddr(page_to_pfn(info->pages[0]))) +
> + frags[0].offset) - NET_IP_ALIGN - NET_SKB_PAD);
> + info->user.size = iov[0].iov_len + NET_IP_ALIGN + NET_SKB_PAD;
> + }
> + return info;
> +
> +failed:
> + for (i = 0; i < j; i++)
> + put_page(info->pages[i]);
For reads, I think you must also mark the page dirty.
> +
> + kmem_cache_free(ctor->cache, info);
> +
> + return NULL;
> +}
> +
> +struct page_ctor *mp_rcu_get_ctor(struct page_ctor *ctor)
> +{
> + struct page_ctor *_ctor = NULL;
> +
> + rcu_read_lock();
> + _ctor = rcu_dereference(ctor);
> +
> + if (!_ctor) {
> + DBG(KERN_INFO "Device %s cannot do mediate passthru.\n",
> + ctor->dev->name);
> + rcu_read_unlock();
> + return NULL;
> + }
> + get_page_ctor(_ctor);
> + rcu_read_unlock();
> + return _ctor;
So you take a reference to ctor under rcu, but then you keep it
after going outside rcu read side critical section.
This does not seem right.
> +}
> +
> +static int mp_sendmsg(struct kiocb *iocb, struct socket *sock,
> + struct msghdr *m, size_t total_len)
> +{
> + struct mp_struct *mp = container_of(sock->sk, struct mp_sock, sk)->mp;
> + struct page_ctor *ctor;
> + struct vhost_virtqueue *vq = (struct vhost_virtqueue *)(m->msg_control);
> + struct iovec *iov = m->msg_iov;
> + struct page_info *info = NULL;
> + struct frag frags[MAX_SKB_FRAGS];
> + struct sk_buff *skb;
> + int count = m->msg_iovlen;
> + int total = 0, header, n, i, len, rc;
> + unsigned long base;
> +
> + ctor = mp_rcu_get_ctor(mp->ctor);
> + if (!ctor)
> + return -ENODEV;
> +
> + ctor->sendctrl = vq;
> +
> + total = iov_length(iov, count);
> +
> + if (total < ETH_HLEN) {
> + put_page_ctor(ctor);
> + return -EINVAL;
> + }
> +
> + if (total <= COPY_THRESHOLD)
> + goto copy;
> +
> + n = 0;
> + for (i = 0; i < count; i++) {
> + base = (unsigned long)iov[i].iov_base;
> + len = iov[i].iov_len;
> + if (!len)
> + continue;
> + n += ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT;
> + if (n > MAX_SKB_FRAGS) {
> + put_page_ctor(ctor);
> + return -EINVAL;
> + }
> + }
> +
> +copy:
> + header = total > COPY_THRESHOLD ? COPY_HDR_LEN : total;
> +
> + skb = alloc_skb(header + NET_IP_ALIGN, GFP_ATOMIC);
> + if (!skb)
> + goto drop;
> +
> + skb_reserve(skb, NET_IP_ALIGN);
> +
> + skb_set_network_header(skb, ETH_HLEN);
> +
> + memcpy_fromiovec(skb->data, iov, header);
> + skb_put(skb, header);
> + skb->protocol = *((__be16 *)(skb->data) + ETH_ALEN);
> +
> + if (header == total) {
> + rc = total;
> + info = alloc_small_page_info(ctor, total);
> + } else {
> + info = alloc_page_info(ctor, iov, count, frags, 0, total);
> + if (info)
> + for (i = 0; info->pages[i]; i++) {
> + skb_add_rx_frag(skb, i, info->pages[i],
> + frags[i].offset, frags[i].size);
> + info->pages[i] = NULL;
> + }
> + }
> + if (info != NULL) {
> + info->desc_pos = vq->head;
> + info->ctl = vq;
> + info->total = total;
> + info->skb = skb;
> + skb_shinfo(skb)->destructor_arg = &info->user;
> + skb->dev = mp->dev;
> + dev_queue_xmit(skb);
> + mp->dev->stats.tx_packets++;
> + mp->dev->stats.tx_bytes += total;
> + put_page_ctor(ctor);
> + return 0;
> + }
> +drop:
> + kfree(skb);
> + if (info) {
> + for (i = 0; info->pages[i]; i++)
> + put_page(info->pages[i]);
> + kmem_cache_free(info->ctor->cache, info);
> + }
> + mp->dev->stats.tx_dropped++;
> + put_page_ctor(ctor);
> + return -ENOMEM;
> +}
> +
> +
> +static struct vhost_notifier *create_vhost_notifier(struct vhost_virtqueue *vq,
> + struct page_info *info, int size)
> +{
> + struct vhost_notifier *vnotify = NULL;
> +
> + vnotify = &info->notifier;
> + memset(vnotify, 0, sizeof(struct vhost_notifier));
> + vnotify->vq = vq;
> + vnotify->head = info->desc_pos;
> + vnotify->size = size;
> + vnotify->log = info->log;
> + vnotify->ctrl = (void *)info;
> + vnotify->dtor = mp_vhost_notifier_dtor;
> + return vnotify;
> +}
> +
> +static void mp_recvmsg_notify(struct vhost_virtqueue *vq)
> +{
> + struct socket *sock = vq->private_data;
> + struct mp_struct *mp = container_of(sock->sk, struct mp_sock, sk)->mp;
> + struct page_ctor *ctor = NULL;
> + struct sk_buff *skb = NULL;
> + struct page_info *info = NULL;
> + struct ethhdr *eth;
> + struct vhost_notifier *vnotify = NULL;
> + int len, i;
> + unsigned long flags;
> +
> + struct virtio_net_hdr hdr = {
> + .flags = 0,
> + .gso_type = VIRTIO_NET_HDR_GSO_NONE
> + };
> +
> + ctor = mp_rcu_get_ctor(mp->ctor);
> + if (!ctor)
> + return;
> +
> + while ((skb = skb_dequeue(&sock->sk->sk_receive_queue)) != NULL) {
> + if (skb_shinfo(skb)->destructor_arg) {
> + info = container_of(skb_shinfo(skb)->destructor_arg,
> + struct page_info, user);
> + info->skb = skb;
> + if (skb->len > info->len) {
> + mp->dev->stats.rx_dropped++;
> + DBG(KERN_INFO "Discarded truncated rx packet: "
> + " len %d > %zd\n", skb->len, info->len);
> + info->total = skb->len;
> + goto clean;
> + } else {
> + int i;
> + struct skb_shared_info *gshinfo =
> + (struct skb_shared_info *)(&info->ushinfo);
> + struct skb_shared_info *hshinfo =
> + skb_shinfo(skb);
> +
> + if (gshinfo->nr_frags < hshinfo->nr_frags)
> + goto clean;
> + eth = eth_hdr(skb);
> + skb_push(skb, ETH_HLEN);
> +
> + hdr.hdr_len = skb_headlen(skb);
> + info->total = skb->len;
> +
> + for (i = 0; i < gshinfo->nr_frags; i++)
> + gshinfo->frags[i].size = 0;
> + for (i = 0; i < hshinfo->nr_frags; i++)
> + gshinfo->frags[i].size =
> + hshinfo->frags[i].size;
> + memcpy(skb_shinfo(skb), &info->ushinfo,
> + sizeof(struct skb_shared_info));
> + }
> + } else {
> + /* The skb composed with kernel buffers
> + * in case user space buffers are not sufficent.
> + * The case should be rare.
> + */
> + unsigned long flags;
> + int i;
> + struct skb_shared_info *gshinfo = NULL;
> +
> + info = NULL;
> +
> + spin_lock_irqsave(&ctor->read_lock, flags);
> + if (!list_empty(&ctor->readq)) {
> + info = list_first_entry(&ctor->readq,
> + struct page_info, list);
> + list_del(&info->list);
> + }
> + spin_unlock_irqrestore(&ctor->read_lock, flags);
> + if (!info) {
> + DBG(KERN_INFO "No user buffer avaliable %p\n",
> + skb);
> + skb_queue_head(&sock->sk->sk_receive_queue,
> + skb);
> + break;
> + }
> + info->skb = skb;
> + /* compute the guest skb frags info */
> + gshinfo = (struct skb_shared_info *)(info->user.start +
> + SKB_DATA_ALIGN(info->user.size));
> +
> + if (gshinfo->nr_frags < skb_shinfo(skb)->nr_frags)
> + goto clean;
> +
> + eth = eth_hdr(skb);
> + skb_push(skb, ETH_HLEN);
> + info->total = skb->len;
> +
> + for (i = 0; i < gshinfo->nr_frags; i++)
> + gshinfo->frags[i].size = 0;
> + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
> + gshinfo->frags[i].size =
> + skb_shinfo(skb)->frags[i].size;
> + hdr.hdr_len = min_t(int, skb->len,
> + info->iov[1].iov_len);
> + skb_copy_datagram_iovec(skb, 0, info->iov, skb->len);
> + }
> +
> + len = memcpy_toiovec(info->hdr, (unsigned char *)&hdr,
> + sizeof hdr);
> + if (len) {
> + DBG(KERN_INFO
> + "Unable to write vnet_hdr at addr %p: %d\n",
> + info->hdr->iov_base, len);
> + goto clean;
> + }
> + vnotify = create_vhost_notifier(vq, info,
> + skb->len + sizeof(hdr));
> +
> + spin_lock_irqsave(&vq->notify_lock, flags);
> + list_add_tail(&vnotify->list, &vq->notifier);
> + spin_unlock_irqrestore(&vq->notify_lock, flags);
> + continue;
> +
> +clean:
> + kfree_skb(skb);
> + for (i = 0; info->pages[i]; i++)
> + put_page(info->pages[i]);
> + kmem_cache_free(ctor->cache, info);
> + }
> + put_page_ctor(ctor);
> + return;
> +}
> +
> +static int mp_recvmsg(struct kiocb *iocb, struct socket *sock,
> + struct msghdr *m, size_t total_len,
> + int flags)
> +{
> + struct mp_struct *mp = container_of(sock->sk, struct mp_sock, sk)->mp;
> + struct page_ctor *ctor;
> + struct vhost_virtqueue *vq = (struct vhost_virtqueue *)(m->msg_control);
> + struct iovec *iov = m->msg_iov;
> + int count = m->msg_iovlen;
> + int npages, payload;
> + struct page_info *info;
> + struct frag frags[MAX_SKB_FRAGS];
> + unsigned long base;
> + int i, len;
> + unsigned long flag;
> +
> + if (!(flags & MSG_DONTWAIT))
> + return -EINVAL;
> +
> + ctor = mp_rcu_get_ctor(mp->ctor);
> + if (!ctor)
> + return -EINVAL;
> +
> + ctor->recvctrl = vq;
> +
> + /* Error detections in case invalid user space buffer */
> + if (count > 2 && iov[1].iov_len < ctor->port.hdr_len &&
> + mp->dev->features & NETIF_F_SG) {
> + put_page_ctor(ctor);
> + return -EINVAL;
> + }
> +
> + npages = ctor->port.npages;
> + payload = ctor->port.data_len;
> +
> + /* If KVM guest virtio-net FE driver use SG feature */
> + if (count > 2) {
> + for (i = 2; i < count; i++) {
> + base = (unsigned long)iov[i].iov_base & ~PAGE_MASK;
> + len = iov[i].iov_len;
> + if (npages == 1)
> + len = min_t(int, len, PAGE_SIZE - base);
> + else if (base)
> + break;
> + payload -= len;
> + if (payload <= 0)
> + goto proceed;
> + if (npages == 1 || (len & ~PAGE_MASK))
> + break;
> + }
> + }
> +
> + if ((((unsigned long)iov[1].iov_base & ~PAGE_MASK)
> + - NET_SKB_PAD - NET_IP_ALIGN) >= 0)
> + goto proceed;
> +
> + put_page_ctor(ctor);
> + return -EINVAL;
> +
> +proceed:
> + /* skip the virtnet head */
> + iov++;
> + count--;
> +
> + /* Translate address to kernel */
> + info = alloc_page_info(ctor, iov, count, frags, npages, 0);
> + if (!info) {
> + put_page_ctor(ctor);
> + return -ENOMEM;
> + }
> +
> + info->len = total_len;
> + info->hdr[0].iov_base = vq->hdr[0].iov_base;
> + info->hdr[0].iov_len = vq->hdr[0].iov_len;
> + info->offset = frags[0].offset;
> + info->desc_pos = vq->head;
> + info->log = vq->_log;
> + info->ctl = NULL;
> +
> + iov--;
> + count++;
> +
> + memcpy(info->iov, vq->iov, sizeof(struct iovec) * count);
> +
> + spin_lock_irqsave(&ctor->read_lock, flag);
> + list_add_tail(&info->list, &ctor->readq);
> + spin_unlock_irqrestore(&ctor->read_lock, flag);
> +
> + if (!vq->receiver)
> + vq->receiver = mp_recvmsg_notify;
> +
> + put_page_ctor(ctor);
> + return 0;
> +}
> +
> +static void mp_put(struct mp_file *mfile);
> +
> +static int mp_release(struct socket *sock)
> +{
> + struct mp_struct *mp = container_of(sock->sk, struct mp_sock, sk)->mp;
> + struct mp_file *mfile = mp->mfile;
> +
> + mp_put(mfile);
> + sock_put(mp->socket.sk);
> + put_net(mfile->net);
> +
> + return 0;
> +}
> +
> +/* Ops structure to mimic raw sockets with mp device */
> +static const struct proto_ops mp_socket_ops = {
> + .sendmsg = mp_sendmsg,
> + .recvmsg = mp_recvmsg,
> + .release = mp_release,
> +};
> +
> +static struct proto mp_proto = {
> + .name = "mp",
> + .owner = THIS_MODULE,
> + .obj_size = sizeof(struct mp_sock),
> +};
> +
> +static int mp_chr_open(struct inode *inode, struct file * file)
> +{
> + struct mp_file *mfile;
> + cycle_kernel_lock();
> + DBG1(KERN_INFO "mp: mp_chr_open\n");
> +
> + mfile = kzalloc(sizeof(*mfile), GFP_KERNEL);
> + if (!mfile)
> + return -ENOMEM;
> + atomic_set(&mfile->count, 0);
> + mfile->mp = NULL;
> + mfile->net = get_net(current->nsproxy->net_ns);
> + file->private_data = mfile;
> + return 0;
> +}
> +
> +static void __mp_detach(struct mp_struct *mp)
> +{
> + mp->mfile = NULL;
> +
> + mp_dev_change_flags(mp->dev, mp->dev->flags & ~IFF_UP);
> + page_ctor_detach(mp);
> + mp_dev_change_flags(mp->dev, mp->dev->flags | IFF_UP);
> +
> + /* Drop the extra count on the net device */
> + dev_put(mp->dev);
> +}
> +
> +static DEFINE_MUTEX(mp_mutex);
> +
> +static void mp_detach(struct mp_struct *mp)
> +{
> + mutex_lock(&mp_mutex);
> + __mp_detach(mp);
> + mutex_unlock(&mp_mutex);
> +}
> +
> +static struct mp_struct *mp_get(struct mp_file *mfile)
> +{
> + struct mp_struct *mp = NULL;
> + if (atomic_inc_not_zero(&mfile->count))
> + mp = mfile->mp;
> +
> + return mp;
> +}
> +
> +static void mp_put(struct mp_file *mfile)
> +{
> + if (atomic_dec_and_test(&mfile->count))
> + mp_detach(mfile->mp);
> +}
> +
> +static int mp_attach(struct mp_struct *mp, struct file *file)
> +{
> + struct mp_file *mfile = file->private_data;
> + int err;
> +
> + netif_tx_lock_bh(mp->dev);
> +
> + err = -EINVAL;
> +
> + if (mfile->mp)
> + goto out;
> +
> + err = -EBUSY;
> + if (mp->mfile)
> + goto out;
> +
> + err = 0;
> + mfile->mp = mp;
> + mp->mfile = mfile;
> + mp->socket.file = file;
> + dev_hold(mp->dev);
> + sock_hold(mp->socket.sk);
> + atomic_inc(&mfile->count);
> +
> +out:
> + netif_tx_unlock_bh(mp->dev);
> + return err;
> +}
> +
> +static void mp_sock_destruct(struct sock *sk)
> +{
> + struct mp_struct *mp = container_of(sk, struct mp_sock, sk)->mp;
> + kfree(mp);
> +}
> +
> +static int do_unbind(struct mp_file *mfile)
> +{
> + struct mp_struct *mp = mp_get(mfile);
> +
> + if (!mp)
> + return -EINVAL;
> +
> + mp_detach(mp);
> + sock_put(mp->socket.sk);
> + mp_put(mfile);
> + return 0;
> +}
> +
> +static void mp_sock_data_ready(struct sock *sk, int len)
> +{
> + if (sk_has_sleeper(sk))
> + wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN);
> +}
> +
> +static void mp_sock_write_space(struct sock *sk)
> +{
> + if (sk_has_sleeper(sk))
> + wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT);
> +}
> +
> +static long mp_chr_ioctl(struct file *file, unsigned int cmd,
> + unsigned long arg)
> +{
> + struct mp_file *mfile = file->private_data;
> + struct mp_struct *mp;
> + struct net_device *dev;
> + void __user* argp = (void __user *)arg;
> + struct ifreq ifr;
> + struct sock *sk;
> + int ret;
> +
> + ret = -EINVAL;
> +
> + switch (cmd) {
> + case MPASSTHRU_BINDDEV:
> + ret = -EFAULT;
> + if (copy_from_user(&ifr, argp, sizeof ifr))
> + break;
> +
> + ifr.ifr_name[IFNAMSIZ-1] = '\0';
> +
> + ret = -EBUSY;
> +
> + if (ifr.ifr_flags & IFF_MPASSTHRU_EXCL)
> + break;
> +
> + ret = -ENODEV;
> + dev = dev_get_by_name(mfile->net, ifr.ifr_name);
> + if (!dev)
> + break;
> +
> + mutex_lock(&mp_mutex);
> +
> + ret = -EBUSY;
> + mp = mfile->mp;
> + if (mp)
> + goto err_dev_put;
> +
> + mp = kzalloc(sizeof(*mp), GFP_KERNEL);
> + if (!mp) {
> + ret = -ENOMEM;
> + goto err_dev_put;
> + }
> + mp->dev = dev;
> + ret = -ENOMEM;
> +
> + sk = sk_alloc(mfile->net, AF_UNSPEC, GFP_KERNEL, &mp_proto);
> + if (!sk)
> + goto err_free_mp;
> +
> + init_waitqueue_head(&mp->socket.wait);
> + mp->socket.ops = &mp_socket_ops;
> + sock_init_data(&mp->socket, sk);
> + sk->sk_sndbuf = INT_MAX;
> + container_of(sk, struct mp_sock, sk)->mp = mp;
> +
> + sk->sk_destruct = mp_sock_destruct;
> + sk->sk_data_ready = mp_sock_data_ready;
> + sk->sk_write_space = mp_sock_write_space;
> +
> + ret = mp_attach(mp, file);
> + if (ret < 0)
> + goto err_free_sk;
> +
> + ret = page_ctor_attach(mp);
> + if (ret < 0)
> + goto err_free_sk;
> +
> + ifr.ifr_flags |= IFF_MPASSTHRU_EXCL;
> + mp_dev_change_flags(mp->dev, mp->dev->flags | IFF_UP);
> +out:
> + mutex_unlock(&mp_mutex);
> + break;
> +err_free_sk:
> + sk_free(sk);
> +err_free_mp:
> + kfree(mp);
> +err_dev_put:
> + dev_put(dev);
> + goto out;
> +
> + case MPASSTHRU_UNBINDDEV:
> + ret = do_unbind(mfile);
> + break;
> +
> + default:
> + break;
> + }
> + return ret;
> +}
> +
> +static unsigned int mp_chr_poll(struct file *file, poll_table * wait)
> +{
> + struct mp_file *mfile = file->private_data;
> + struct mp_struct *mp = mp_get(mfile);
> + struct sock *sk;
> + unsigned int mask = 0;
> +
> + if (!mp)
> + return POLLERR;
> +
> + sk = mp->socket.sk;
> +
> + poll_wait(file, &mp->socket.wait, wait);
> +
> + if (!skb_queue_empty(&sk->sk_receive_queue))
> + mask |= POLLIN | POLLRDNORM;
> +
> + if (sock_writeable(sk) ||
> + (!test_and_set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
> + sock_writeable(sk)))
> + mask |= POLLOUT | POLLWRNORM;
> +
> + if (mp->dev->reg_state != NETREG_REGISTERED)
> + mask = POLLERR;
> +
> + mp_put(mfile);
> + return mask;
> +}
> +
> +static int mp_chr_close(struct inode *inode, struct file *file)
> +{
> + struct mp_file *mfile = file->private_data;
> +
> + /*
> + * Ignore return value since an error only means there was nothing to
> + * do
> + */
> + do_unbind(mfile);
> +
> + put_net(mfile->net);
> + kfree(mfile);
> +
> + return 0;
> +}
> +
> +static const struct file_operations mp_fops = {
> + .owner = THIS_MODULE,
> + .llseek = no_llseek,
> + .poll = mp_chr_poll,
> + .unlocked_ioctl = mp_chr_ioctl,
> + .open = mp_chr_open,
> + .release = mp_chr_close,
qemu will need a way to send packets from userspace
(not from guest) as well. So I think you will need
a write as well.
> +};
> +
> +static struct miscdevice mp_miscdev = {
> + .minor = MISC_DYNAMIC_MINOR,
> + .name = "mp",
> + .nodename = "net/mp",
> + .fops = &mp_fops,
> +};
> +
> +static int mp_device_event(struct notifier_block *unused,
> + unsigned long event, void *ptr)
> +{
> + struct net_device *dev = ptr;
> + struct mpassthru_port *port;
> + struct mp_struct *mp = NULL;
> + struct socket *sock = NULL;
> +
> + port = dev->mp_port;
> + if (port == NULL)
> + return NOTIFY_DONE;
> +
> + switch (event) {
> + case NETDEV_UNREGISTER:
> + sock = dev->mp_port->sock;
> + mp = container_of(sock->sk, struct mp_sock, sk)->mp;
> + do_unbind(mp->mfile);
> + break;
> + }
> + return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block mp_notifier_block __read_mostly = {
> + .notifier_call = mp_device_event,
> +};
> +
> +static int mp_init(void)
> +{
> + int ret = 0;
> +
> + ret = misc_register(&mp_miscdev);
> + if (ret)
> + printk(KERN_ERR "mp: Can't register misc device\n");
> + else {
> + printk(KERN_INFO "Registering mp misc device - minor = %d\n",
> + mp_miscdev.minor);
> + register_netdevice_notifier(&mp_notifier_block);
> + }
> + return ret;
> +}
> +
> +void mp_cleanup(void)
> +{
> + unregister_netdevice_notifier(&mp_notifier_block);
> + misc_deregister(&mp_miscdev);
> +}
> +
> +/* Get an underlying socket object from mp file. Returns error unless file is
> + * attached to a device. The returned object works like a packet socket, it
> + * can be used for sock_sendmsg/sock_recvmsg. The caller is responsible for
> + * holding a reference to the file for as long as the socket is in use. */
> +struct socket *mp_get_socket(struct file *file)
> +{
> + struct mp_file *mfile = file->private_data;
> + struct mp_struct *mp;
> +
> + if (file->f_op != &mp_fops)
> + return ERR_PTR(-EINVAL);
> + mp = mp_get(mfile);
> + if (!mp)
> + return ERR_PTR(-EBADFD);
> + mp_put(mfile);
> + return &mp->socket;
> +}
> +EXPORT_SYMBOL_GPL(mp_get_socket);
> +
> +module_init(mp_init);
> +module_exit(mp_cleanup);
> +MODULE_AUTHOR(DRV_COPYRIGHT);
> +MODULE_DESCRIPTION(DRV_DESCRIPTION);
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/mpassthru.h b/include/linux/mpassthru.h
> new file mode 100644
> index 0000000..2be21c5
> --- /dev/null
> +++ b/include/linux/mpassthru.h
> @@ -0,0 +1,29 @@
> +#ifndef __MPASSTHRU_H
> +#define __MPASSTHRU_H
> +
> +#include <linux/types.h>
> +#include <linux/if_ether.h>
> +
> +/* ioctl defines */
> +#define MPASSTHRU_BINDDEV _IOW('M', 213, int)
> +#define MPASSTHRU_UNBINDDEV _IOW('M', 214, int)
> +
> +/* MPASSTHRU ifc flags */
> +#define IFF_MPASSTHRU 0x0001
> +#define IFF_MPASSTHRU_EXCL 0x0002
> +
> +#ifdef __KERNEL__
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> +struct socket *mp_get_socket(struct file *);
> +#else
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +struct file;
> +struct socket;
> +static inline struct socket *mp_get_socket(struct file *f)
> +{
> + return ERR_PTR(-EINVAL);
> +}
> +#endif /* CONFIG_VHOST_PASSTHRU */
> +#endif /* __KERNEL__ */
> +#endif /* __MPASSTHRU_H */
> --
> 1.5.4.4
^ permalink raw reply
* Re: [PATCH v1 3/3] Let host NIC driver to DMA to guest user space.
From: Michael S. Tsirkin @ 2010-03-08 11:18 UTC (permalink / raw)
To: xiaohui.xin; +Cc: netdev, kvm, linux-kernel, mingo, jdike, Zhao Yu
In-Reply-To: <1267868318-19268-4-git-send-email-xiaohui.xin@intel.com>
On Sat, Mar 06, 2010 at 05:38:38PM +0800, xiaohui.xin@intel.com wrote:
> From: Xin Xiaohui <xiaohui.xin@intel.com>
>
> The patch let host NIC driver to receive user space skb,
> then the driver has chance to directly DMA to guest user
> space buffers thru single ethX interface.
>
> Signed-off-by: Xin Xiaohui <xiaohui.xin@intel.com>
> Signed-off-by: Zhao Yu <yzhao81@gmail.com>
> Sigend-off-by: Jeff Dike <jdike@c2.user-mode-linux.org>
I have a feeling I commented on some of the below issues already.
Do you plan to send a version with comments addressed?
> ---
> include/linux/netdevice.h | 76 ++++++++++++++++++++++++++++++++++++++++++-
> include/linux/skbuff.h | 30 +++++++++++++++--
> net/core/dev.c | 32 ++++++++++++++++++
> net/core/skbuff.c | 79 +++++++++++++++++++++++++++++++++++++++++----
> 4 files changed, 205 insertions(+), 12 deletions(-)
>
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 94958c1..97bf12c 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -485,6 +485,17 @@ struct netdev_queue {
> unsigned long tx_dropped;
> } ____cacheline_aligned_in_smp;
>
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> +struct mpassthru_port {
> + int hdr_len;
> + int data_len;
> + int npages;
> + unsigned flags;
> + struct socket *sock;
> + struct skb_user_page *(*ctor)(struct mpassthru_port *,
> + struct sk_buff *, int);
> +};
> +#endif
>
> /*
> * This structure defines the management hooks for network devices.
> @@ -636,6 +647,10 @@ struct net_device_ops {
> int (*ndo_fcoe_ddp_done)(struct net_device *dev,
> u16 xid);
> #endif
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + int (*ndo_mp_port_prep)(struct net_device *dev,
> + struct mpassthru_port *port);
> +#endif
> };
>
> /*
> @@ -891,7 +906,8 @@ struct net_device
> struct macvlan_port *macvlan_port;
> /* GARP */
> struct garp_port *garp_port;
> -
> + /* mpassthru */
> + struct mpassthru_port *mp_port;
> /* class/net/name entry */
> struct device dev;
> /* space for optional statistics and wireless sysfs groups */
> @@ -2013,6 +2029,62 @@ static inline u32 dev_ethtool_get_flags(struct net_device *dev)
> return 0;
> return dev->ethtool_ops->get_flags(dev);
> }
> -#endif /* __KERNEL__ */
>
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> +static inline int netdev_mp_port_prep(struct net_device *dev,
> + struct mpassthru_port *port)
> +{
This function lacks documentation.
> + int rc;
> + int npages, data_len;
> + const struct net_device_ops *ops = dev->netdev_ops;
> +
> + /* needed by packet split */
> + if (ops->ndo_mp_port_prep) {
> + rc = ops->ndo_mp_port_prep(dev, port);
> + if (rc)
> + return rc;
> + } else { /* should be temp */
> + port->hdr_len = 128;
> + port->data_len = 2048;
> + port->npages = 1;
where do the numbers come from?
> + }
> +
> + if (port->hdr_len <= 0)
> + goto err;
> +
> + npages = port->npages;
> + data_len = port->data_len;
> + if (npages <= 0 || npages > MAX_SKB_FRAGS ||
> + (data_len < PAGE_SIZE * (npages - 1) ||
> + data_len > PAGE_SIZE * npages))
> + goto err;
> +
> + return 0;
> +err:
> + dev_warn(&dev->dev, "invalid page constructor parameters\n");
> +
> + return -EINVAL;
> +}
> +
> +static inline int netdev_mp_port_attach(struct net_device *dev,
> + struct mpassthru_port *port)
> +{
> + if (rcu_dereference(dev->mp_port))
> + return -EBUSY;
> +
> + rcu_assign_pointer(dev->mp_port, port);
> +
> + return 0;
> +}
> +
> +static inline void netdev_mp_port_detach(struct net_device *dev)
> +{
> + if (!rcu_dereference(dev->mp_port))
> + return;
> +
> + rcu_assign_pointer(dev->mp_port, NULL);
> + synchronize_rcu();
> +}
The above looks wrong, rcu_dereference should be called
under rcu read side, rcu_assign_pointer usually should not,
synchronize_rcu definitely should not.
As I suggested already, these functions are better opencoded,
rcu is tricky as is without hiding it in inline helpers.
> +#endif /* CONFIG_VHOST_PASSTHRU */
> +#endif /* __KERNEL__ */
> #endif /* _LINUX_NETDEVICE_H */
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index df7b23a..e59fa57 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -209,6 +209,13 @@ struct skb_shared_info {
> void * destructor_arg;
> };
>
> +struct skb_user_page {
> + u8 *start;
> + int size;
> + struct skb_frag_struct *frags;
> + struct skb_shared_info *ushinfo;
> + void (*dtor)(struct skb_user_page *);
> +};
> /* We divide dataref into two halves. The higher 16 bits hold references
> * to the payload part of skb->data. The lower 16 bits hold references to
> * the entire skb->data. A clone of a headerless skb holds the length of
> @@ -441,17 +448,18 @@ extern void kfree_skb(struct sk_buff *skb);
> extern void consume_skb(struct sk_buff *skb);
> extern void __kfree_skb(struct sk_buff *skb);
> extern struct sk_buff *__alloc_skb(unsigned int size,
> - gfp_t priority, int fclone, int node);
> + gfp_t priority, int fclone,
> + int node, struct net_device *dev);
> static inline struct sk_buff *alloc_skb(unsigned int size,
> gfp_t priority)
> {
> - return __alloc_skb(size, priority, 0, -1);
> + return __alloc_skb(size, priority, 0, -1, NULL);
> }
>
> static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
> gfp_t priority)
> {
> - return __alloc_skb(size, priority, 1, -1);
> + return __alloc_skb(size, priority, 1, -1, NULL);
> }
>
> extern int skb_recycle_check(struct sk_buff *skb, int skb_size);
> @@ -1509,6 +1517,22 @@ static inline void netdev_free_page(struct net_device *dev, struct page *page)
> __free_page(page);
> }
>
> +extern struct skb_user_page *netdev_alloc_user_pages(struct net_device *dev,
> + struct sk_buff *skb, int npages);
> +
> +static inline struct skb_user_page *netdev_alloc_user_page(
> + struct net_device *dev,
> + struct sk_buff *skb, unsigned int size)
> +{
> + struct skb_user_page *user;
> + int npages = (size < PAGE_SIZE) ? 1 : (size / PAGE_SIZE);
Should round up to full pages?
> +
> + user = netdev_alloc_user_pages(dev, skb, npages);
> + if (likely(user))
> + return user;
> + return NULL;
> +}
> +
> /**
> * skb_clone_writable - is the header of a clone writable
> * @skb: buffer to check
> diff --git a/net/core/dev.c b/net/core/dev.c
> index b8f74cf..ab8b082 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -2265,6 +2265,30 @@ void netif_nit_deliver(struct sk_buff *skb)
> rcu_read_unlock();
> }
>
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> +static inline struct sk_buff *handle_mpassthru(struct sk_buff *skb,
> + struct packet_type **pt_prev,
> + int *ret, struct net_device *orig_dev)
please document
pt_prev, orig_dev and ret seem unused?
> +{
> + struct mpassthru_port *ctor = NULL;
Why do you call the port "ctor"?
> + struct sock *sk = NULL;
> +
> + if (skb->dev)
> + ctor = skb->dev->mp_port;
> + if (!ctor)
> + return skb;
> +
> + sk = ctor->sock->sk;
> +
> + skb_queue_tail(&sk->sk_receive_queue, skb);
> +
> + sk->sk_data_ready(sk, skb->len);
> + return NULL;
> +}
> +#else
> +#define handle_mpassthru(skb, pt_prev, ret, orig_dev) (skb)
> +#endif
> +
> /**
> * netif_receive_skb - process receive buffer from network
> * @skb: buffer to process
> @@ -2342,6 +2366,9 @@ int netif_receive_skb(struct sk_buff *skb)
> goto out;
> ncls:
> #endif
> + skb = handle_mpassthru(skb, &pt_prev, &ret, orig_dev);
> + if (!skb)
> + goto out;
>
> skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
> if (!skb)
> @@ -2455,6 +2482,11 @@ int dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
> if (skb_is_gso(skb) || skb_has_frags(skb))
> goto normal;
>
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + if (skb->dev && skb->dev->mp_port)
> + goto normal;
> +#endif
> +
> rcu_read_lock();
> list_for_each_entry_rcu(ptype, head, list) {
> if (ptype->type != type || ptype->dev || !ptype->gro_receive)
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 80a9616..6510e5b 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -170,13 +170,15 @@ EXPORT_SYMBOL(skb_under_panic);
> * %GFP_ATOMIC.
> */
> struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
> - int fclone, int node)
> + int fclone, int node, struct net_device *dev)
> {
> struct kmem_cache *cache;
> struct skb_shared_info *shinfo;
> struct sk_buff *skb;
> u8 *data;
> -
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + struct skb_user_page *user = NULL;
> +#endif
> cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
>
> /* Get the HEAD */
> @@ -185,8 +187,26 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
> goto out;
>
> size = SKB_DATA_ALIGN(size);
> - data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info),
> - gfp_mask, node);
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + if (!dev || !dev->mp_port) { /* Legacy alloc func */
> +#endif
> + data = kmalloc_node_track_caller(
> + size + sizeof(struct skb_shared_info),
> + gfp_mask, node);
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + } else { /* Allocation may from page constructor of device */
what does the comment mean?
> + user = netdev_alloc_user_page(dev, skb, size);
> + if (!user) {
> + data = kmalloc_node_track_caller(
> + size + sizeof(struct skb_shared_info),
> + gfp_mask, node);
> + printk(KERN_INFO "can't alloc user buffer.\n");
> + } else {
> + data = user->start;
> + size = SKB_DATA_ALIGN(user->size);
> + }
> + }
> +#endif
> if (!data)
> goto nodata;
>
> @@ -208,6 +228,11 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
> skb->mac_header = ~0U;
> #endif
>
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + if (user)
> + memcpy(user->ushinfo, skb_shinfo(skb),
> + sizeof(struct skb_shared_info));
> +#endif
> /* make sure we initialize shinfo sequentially */
> shinfo = skb_shinfo(skb);
> atomic_set(&shinfo->dataref, 1);
> @@ -231,6 +256,10 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
>
> child->fclone = SKB_FCLONE_UNAVAILABLE;
> }
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + shinfo->destructor_arg = user;
> +#endif
> +
> out:
> return skb;
> nodata:
> @@ -259,7 +288,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
> int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
> struct sk_buff *skb;
>
> - skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);
> + skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node, dev);
> if (likely(skb)) {
> skb_reserve(skb, NET_SKB_PAD);
> skb->dev = dev;
> @@ -278,6 +307,29 @@ struct page *__netdev_alloc_page(struct net_device *dev, gfp_t gfp_mask)
> }
> EXPORT_SYMBOL(__netdev_alloc_page);
>
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> +struct skb_user_page *netdev_alloc_user_pages(struct net_device *dev,
> + struct sk_buff *skb, int npages)
> +{
> + struct mpassthru_port *ctor;
> + struct skb_user_page *user = NULL;
> +
> + rcu_read_lock();
> + ctor = rcu_dereference(dev->mp_port);
> + if (!ctor)
> + goto out;
> +
> + BUG_ON(npages > ctor->npages);
> +
> + user = ctor->ctor(ctor, skb, npages);
With the assumption that "ctor" pins userspace pages,
can't it sleep? If yes you can't call it under rcu read side
critical section.
> +out:
> + rcu_read_unlock();
> +
> + return user;
> +}
> +EXPORT_SYMBOL(netdev_alloc_user_pages);
> +#endif
> +
> void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
> int size)
> {
> @@ -338,6 +390,10 @@ static void skb_clone_fraglist(struct sk_buff *skb)
>
> static void skb_release_data(struct sk_buff *skb)
> {
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + struct skb_user_page *user = skb_shinfo(skb)->destructor_arg;
> +#endif
> +
> if (!skb->cloned ||
> !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
> &skb_shinfo(skb)->dataref)) {
> @@ -349,7 +405,10 @@ static void skb_release_data(struct sk_buff *skb)
>
> if (skb_has_frags(skb))
> skb_drop_fraglist(skb);
> -
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + if (skb->dev && skb->dev->mp_port && user && user->dtor)
> + user->dtor(user);
> +#endif
> kfree(skb->head);
> }
> }
> @@ -503,8 +562,14 @@ int skb_recycle_check(struct sk_buff *skb, int skb_size)
> if (skb_shared(skb) || skb_cloned(skb))
> return 0;
>
> - skb_release_head_state(skb);
> +#if defined(CONFIG_VHOST_PASSTHRU) || defined(CONFIG_VHOST_PASSTHRU_MODULE)
> + if (skb->dev && skb->dev->mp_port)
> + return 0;
> +#endif
> +
> shinfo = skb_shinfo(skb);
> +
> + skb_release_head_state(skb);
> atomic_set(&shinfo->dataref, 1);
> shinfo->nr_frags = 0;
> shinfo->gso_size = 0;
> --
> 1.5.4.4
^ permalink raw reply
* RE: bnx2x crash dump on high network load
From: Fischer, Anna @ 2010-03-08 11:02 UTC (permalink / raw)
To: Eilon Greenstein; +Cc: eliezert, Michael Chan, netdev@vger.kernel.org
In-Reply-To: <BD3F7F1EFBA6D54DB056C4FFA451400803A1F8F2F7@SJEXCHCCR01.corp.ad.broadcom.com>
I have this option set in my /etc/modprobe.conf.local. The problem must be something else.
> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> On Behalf Of Eilon Greenstein
> Sent: 05 March 2010 17:32
> To: Fischer, Anna
> Cc: eliezert; Michael Chan; netdev@vger.kernel.org
> Subject: RE: bnx2x crash dump on high network load
>
> Hi Anna,
>
> On this kernel, enabling bridging (like you do on virtualization) does
> not turn off LRO automatically. Please try to load the bnx2x with
> disable_tpa=1 (TPA is the HW based LRO feature).
>
> Regards,
> Eilon
>
> -----Original Message-----
> From: Fischer, Anna [mailto:anna.fischer@hp.com]
> Sent: Friday, March 05, 2010 7:08 PM
> To: netdev@vger.kernel.org
> Cc: eliezert; Eilon Greenstein; Michael Chan
> Subject: bnx2x crash dump on high network load
>
> I am seeing driver crashes with a bnx2x version 1.50.16. I have attached
> two crash dumps that I have captured.
>
> I run Linux with the following kernel:
>
> # uname -a
> Linux sup-prj-441106 2.6.16.60-0.54.5-debug #1 SMP Fri Sep 4 01:28:03
> UTC 2009 x86_64 x86_64 x86_64 GNU/Linux
>
> I am seeing these driver crashes when I run virtual machines (VMware
> Server) and those VMs do high bandwidth network I/O, so there are a lot
> of packets going through the NIC.
>
> Can you give me any hints for what the problem here could be?
>
> Thanks,
> Anna
>
> --
> 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
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