* [PATCH 5/8] llc: use limited socket backlog
From: Zhu Yi @ 2010-03-03 6:35 UTC (permalink / raw)
To: netdev; +Cc: Zhu Yi, Arnaldo Carvalho de Melo
In-Reply-To: <1267598111-12503-4-git-send-email-yi.zhu@intel.com>
Make llc adapt to the limited socket backlog change.
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
net/llc/llc_c_ac.c | 2 +-
net/llc/llc_conn.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c
index 019c780..86d6985 100644
--- a/net/llc/llc_c_ac.c
+++ b/net/llc/llc_c_ac.c
@@ -1437,7 +1437,7 @@ static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb)
llc_conn_state_process(sk, skb);
else {
llc_set_backlog_type(skb, LLC_EVENT);
- sk_add_backlog(sk, skb);
+ __sk_add_backlog(sk, skb);
}
}
}
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
index a8dde9b..a12144d 100644
--- a/net/llc/llc_conn.c
+++ b/net/llc/llc_conn.c
@@ -827,7 +827,8 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
else {
dprintk("%s: adding to backlog...\n", __func__);
llc_set_backlog_type(skb, LLC_PACKET);
- sk_add_backlog(sk, skb);
+ if (sk_add_backlog(sk, skb))
+ goto drop_unlock;
}
out:
bh_unlock_sock(sk);
--
1.6.3.3
^ permalink raw reply related
* [PATCH 4/8] udp: use limited socket backlog
From: Zhu Yi @ 2010-03-03 6:35 UTC (permalink / raw)
To: netdev
Cc: Zhu Yi, David S. Miller, Alexey Kuznetsov, Pekka Savola (ipv6),
Patrick McHardy
In-Reply-To: <1267598111-12503-3-git-send-email-yi.zhu@intel.com>
Make udp adapt to the limited socket backlog change.
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: "Pekka Savola (ipv6)" <pekkas@netcore.fi>
Cc: Patrick McHardy <kaber@trash.net>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
net/ipv4/udp.c | 6 ++++--
net/ipv6/udp.c | 28 ++++++++++++++++++----------
2 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 608a544..7af756d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1371,8 +1371,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
bh_lock_sock(sk);
if (!sock_owned_by_user(sk))
rc = __udp_queue_rcv_skb(sk, skb);
- else
- sk_add_backlog(sk, skb);
+ else if (sk_add_backlog(sk, skb)) {
+ bh_unlock_sock(sk);
+ goto drop;
+ }
bh_unlock_sock(sk);
return rc;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 52b8347..3c0c9c7 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -583,16 +583,20 @@ static void flush_stack(struct sock **stack, unsigned int count,
bh_lock_sock(sk);
if (!sock_owned_by_user(sk))
udpv6_queue_rcv_skb(sk, skb1);
- else
- sk_add_backlog(sk, skb1);
+ else if (sk_add_backlog(sk, skb1)) {
+ kfree_skb(skb1);
+ bh_unlock_sock(sk);
+ goto drop;
+ }
bh_unlock_sock(sk);
- } else {
- atomic_inc(&sk->sk_drops);
- UDP6_INC_STATS_BH(sock_net(sk),
- UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk));
- UDP6_INC_STATS_BH(sock_net(sk),
- UDP_MIB_INERRORS, IS_UDPLITE(sk));
+ continue;
}
+drop:
+ atomic_inc(&sk->sk_drops);
+ UDP6_INC_STATS_BH(sock_net(sk),
+ UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk));
+ UDP6_INC_STATS_BH(sock_net(sk),
+ UDP_MIB_INERRORS, IS_UDPLITE(sk));
}
}
/*
@@ -754,8 +758,12 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
bh_lock_sock(sk);
if (!sock_owned_by_user(sk))
udpv6_queue_rcv_skb(sk, skb);
- else
- sk_add_backlog(sk, skb);
+ else if (sk_add_backlog(sk, skb)) {
+ atomic_inc(&sk->sk_drops);
+ bh_unlock_sock(sk);
+ sock_put(sk);
+ goto discard;
+ }
bh_unlock_sock(sk);
sock_put(sk);
return 0;
--
1.6.3.3
^ permalink raw reply related
* [PATCH 3/8] tcp: use limited socket backlog
From: Zhu Yi @ 2010-03-03 6:35 UTC (permalink / raw)
To: netdev
Cc: Zhu Yi, David S. Miller, Alexey Kuznetsov, Pekka Savola (ipv6),
Patrick McHardy
In-Reply-To: <1267598111-12503-2-git-send-email-yi.zhu@intel.com>
Make tcp adapt to the limited socket backlog change.
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: "Pekka Savola (ipv6)" <pekkas@netcore.fi>
Cc: Patrick McHardy <kaber@trash.net>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
net/ipv4/tcp_ipv4.c | 6 ++++--
net/ipv4/tcp_minisocks.c | 2 +-
net/ipv6/tcp_ipv6.c | 6 ++++--
3 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c3588b4..1915f7d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1682,8 +1682,10 @@ process:
if (!tcp_prequeue(sk, skb))
ret = tcp_v4_do_rcv(sk, skb);
}
- } else
- sk_add_backlog(sk, skb);
+ } else if (sk_add_backlog(sk, skb)) {
+ bh_unlock_sock(sk);
+ goto discard_and_relse;
+ }
bh_unlock_sock(sk);
sock_put(sk);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index f206ee5..4199bc6 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -728,7 +728,7 @@ int tcp_child_process(struct sock *parent, struct sock *child,
* in main socket hash table and lock on listening
* socket does not protect us more.
*/
- sk_add_backlog(child, skb);
+ __sk_add_backlog(child, skb);
}
bh_unlock_sock(child);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 6963a6b..2c378b1 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1740,8 +1740,10 @@ process:
if (!tcp_prequeue(sk, skb))
ret = tcp_v6_do_rcv(sk, skb);
}
- } else
- sk_add_backlog(sk, skb);
+ } else if (sk_add_backlog(sk, skb)) {
+ bh_unlock_sock(sk);
+ goto discard_and_relse;
+ }
bh_unlock_sock(sk);
sock_put(sk);
--
1.6.3.3
^ permalink raw reply related
* [PATCH 2/8] dccp: use limited socket backlog
From: Zhu Yi @ 2010-03-03 6:35 UTC (permalink / raw)
To: netdev; +Cc: Zhu Yi, Arnaldo Carvalho de Melo
In-Reply-To: <1267598111-12503-1-git-send-email-yi.zhu@intel.com>
Make dccp adapt to the limited socket backlog change.
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
net/dccp/minisocks.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
index af226a0..0d508c3 100644
--- a/net/dccp/minisocks.c
+++ b/net/dccp/minisocks.c
@@ -254,7 +254,7 @@ int dccp_child_process(struct sock *parent, struct sock *child,
* in main socket hash table and lock on listening
* socket does not protect us more.
*/
- sk_add_backlog(child, skb);
+ __sk_add_backlog(child, skb);
}
bh_unlock_sock(child);
--
1.6.3.3
^ permalink raw reply related
* [PATCH 1/8] net: add limit for socket backlog
From: Zhu Yi @ 2010-03-03 6:35 UTC (permalink / raw)
To: netdev
Cc: Zhu Yi, David Miller, Arnaldo Carvalho de Melo,
Pekka Savola (ipv6), Patrick McHardy, Vlad Yasevich,
Sridhar Samudrala, Per Liden, Jon Maloy, Allan Stephens,
Andrew Hendry, Eric Dumazet
We got system OOM while running some UDP netperf testing on the loopback
device. The case is multiple senders sent stream UDP packets to a single
receiver via loopback on local host. Of course, the receiver is not able
to handle all the packets in time. But we surprisingly found that these
packets were not discarded due to the receiver's sk->sk_rcvbuf limit.
Instead, they are kept queuing to sk->sk_backlog and finally ate up all
the memory. We believe this is a secure hole that a none privileged user
can crash the system.
The root cause for this problem is, when the receiver is doing
__release_sock() (i.e. after userspace recv, kernel udp_recvmsg ->
skb_free_datagram_locked -> release_sock), it moves skbs from backlog to
sk_receive_queue with the softirq enabled. In the above case, multiple
busy senders will almost make it an endless loop. The skbs in the
backlog end up eat all the system memory.
The issue is not only for UDP. Any protocols using socket backlog is
potentially affected. The patch adds limit for socket backlog so that
the backlog size cannot be expanded endlessly.
Reported-by: Alex Shi <alex.shi@intel.com>
Cc: David Miller <davem@davemloft.net>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru
Cc: "Pekka Savola (ipv6)" <pekkas@netcore.fi>
Cc: Patrick McHardy <kaber@trash.net>
Cc: Vlad Yasevich <vladislav.yasevich@hp.com>
Cc: Sridhar Samudrala <sri@us.ibm.com>
Cc: Per Liden <per.liden@ericsson.com>
Cc: Jon Maloy <jon.maloy@ericsson.com>
Cc: Allan Stephens <allan.stephens@windriver.com>
Cc: Andrew Hendry <andrew.hendry@gmail.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
---
include/net/sock.h | 17 +++++++++++++++--
net/core/sock.c | 15 +++++++++++++--
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 6cb1676..847119a 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -253,6 +253,8 @@ struct sock {
struct {
struct sk_buff *head;
struct sk_buff *tail;
+ int len;
+ int limit;
} sk_backlog;
wait_queue_head_t *sk_sleep;
struct dst_entry *sk_dst_cache;
@@ -589,8 +591,8 @@ static inline int sk_stream_memory_free(struct sock *sk)
return sk->sk_wmem_queued < sk->sk_sndbuf;
}
-/* The per-socket spinlock must be held here. */
-static inline void sk_add_backlog(struct sock *sk, struct sk_buff *skb)
+/* OOB backlog add */
+static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
{
if (!sk->sk_backlog.tail) {
sk->sk_backlog.head = sk->sk_backlog.tail = skb;
@@ -601,6 +603,17 @@ static inline void sk_add_backlog(struct sock *sk, struct sk_buff *skb)
skb->next = NULL;
}
+/* The per-socket spinlock must be held here. */
+static inline int sk_add_backlog(struct sock *sk, struct sk_buff *skb)
+{
+ if (sk->sk_backlog.len >= max(sk->sk_backlog.limit, sk->sk_rcvbuf >> 1))
+ return -ENOBUFS;
+
+ __sk_add_backlog(sk, skb);
+ sk->sk_backlog.len += skb->truesize;
+ return 0;
+}
+
static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{
return sk->sk_backlog_rcv(sk, skb);
diff --git a/net/core/sock.c b/net/core/sock.c
index fcd397a..fa042bc 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -340,8 +340,12 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested)
rc = sk_backlog_rcv(sk, skb);
mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_);
- } else
- sk_add_backlog(sk, skb);
+ } else if (sk_add_backlog(sk, skb)) {
+ bh_unlock_sock(sk);
+ atomic_inc(&sk->sk_drops);
+ goto discard_and_relse;
+ }
+
bh_unlock_sock(sk);
out:
sock_put(sk);
@@ -1139,6 +1142,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
sock_lock_init(newsk);
bh_lock_sock(newsk);
newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL;
+ newsk->sk_backlog.len = 0;
atomic_set(&newsk->sk_rmem_alloc, 0);
/*
@@ -1542,6 +1546,12 @@ static void __release_sock(struct sock *sk)
bh_lock_sock(sk);
} while ((skb = sk->sk_backlog.head) != NULL);
+
+ /*
+ * Doing the zeroing here guarantee we can not loop forever
+ * while a wild producer attempts to flood us.
+ */
+ sk->sk_backlog.len = 0;
}
/**
@@ -1874,6 +1884,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
sk->sk_allocation = GFP_KERNEL;
sk->sk_rcvbuf = sysctl_rmem_default;
sk->sk_sndbuf = sysctl_wmem_default;
+ sk->sk_backlog.limit = sk->sk_rcvbuf >> 1;
sk->sk_state = TCP_CLOSE;
sk_set_socket(sk, sock);
--
1.6.3.3
^ permalink raw reply related
* Re: Current wireless-testing breaks libpcap: mr_alen should be set
From: Jiri Pirko @ 2010-03-03 6:24 UTC (permalink / raw)
To: Pavel Roskin
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA,
tcpdump-workers-YE1jQ5a0g24KACXWX4p+q9i2O/JbrIOy
In-Reply-To: <1267578048.14049.11.camel@mj>
Wed, Mar 03, 2010 at 02:00:48AM CET, proski-mXXj517/zsQ@public.gmane.org wrote:
>Hello!
>
>The current wireless-testing appears to have some non-wireless bits from
>the upcoming Linux 2.6.34. As a result, libpcap and all capture
>programs that use it are broken.
>
>This patch to libpcap helps:
>
>--- a/pcap-linux.c
>+++ b/pcap-linux.c
>@@ -1563,6 +1563,7 @@ live_open_new(pcap_t *handle, const char
> memset(&mr, 0, sizeof(mr));
> mr.mr_ifindex = handle->md.ifindex;
> mr.mr_type = PACKET_MR_PROMISC;
>+ mr.mr_alen = 6;
> if (setsockopt(sock_fd, SOL_PACKET,
> PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1)
> {
>
>libpcap git doesn't have the fix yet.
>
>The breakage must be coming from the commit 914c8ad2 by Jiri Pirko to
>net/packet/af_packet.c
>
>I think it's very unhelpful to introduce patches that break significant
>userspace functionality without giving the affected programs an advance
>warning.
>
>Also, pulling bleeding edge stuff into wireless-testing before rc1
>appears to be either a mistake or a bad decision.
>
>Sorry for cross-post, but it's an urgent issue. Repliers are encouraged
>to trim the recipient list as necessary.
Sorry about this. Corrected patch will follow.
Jirka
>
>--
>Regards,
>Pavel Roskin
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [Bridge] [PATCH] bridge: per-cpu packet statistics (v3)
From: Eric Dumazet @ 2010-03-03 6:09 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, netdev, bridge
In-Reply-To: <20100302153209.74742a96@nehalam>
Le mardi 02 mars 2010 à 15:32 -0800, Stephen Hemminger a écrit :
> The shared packet statistics are a potential source of slow down
> on bridged traffic. Convert to per-cpu array, but only keep those
> statistics which change per-packet.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>
Thanks Stephen !
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
^ permalink raw reply
* Re: KS8695: possible NAPI issue
From: Dick Hollenbeck @ 2010-03-03 5:01 UTC (permalink / raw)
To: figo zhang; +Cc: Yegor Yefremov, netdev, zealcook
In-Reply-To: <c6ed1ac51003021746n2b246591g880b584550ec5e84@mail.gmail.com>
figo zhang wrote:
> 2010/3/2 Dick Hollenbeck <dick@softplc.com>:
>
>> Yegor Yefremov wrote:
>>
>>> I'm using 2.6.33 kernel and I noticed such a strange behavior:
>>>
>>> after system start I transfer one file via netcat from my development
>>> host, after this transfer the network is not functioning i.e. no pings
>>> possible etc.
>>>
>>> To narrow down the problem I checked out this commit
>>>
>>> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=451f14439847db302e5104c44458b2dbb4b1829d.
>>> Till here the network driver is functioning as intended, but after
>>> NAPI introduction I have this issue. With latest git-pull of "Linus'
>>> kernel tree" I can't even ping right after the systems start.
>>>
>>> Any Ideas? What am I missing?
>>>
>>>
>> No idea, although I am using the same ARM chip, my kernel is at 2.6.30.5,
>> and except for this occasional loss of connection I get, the ethernet driver
>> seems to work better than what you are reporting.
>>
>
> from linux-2.6.32, this ethernet driver have add NAPI support, would
> you like to
> try using this version?
>
Seems like a lot of work for me, given that my 2.6.30.5 kernel is mostly
working. Yegor is having the problems on the newer kernels, newer than
mine. Sounds like a warning flag to me, not an incentive.
What is NAPI and why do I care?
Dick
^ permalink raw reply
* Re: 2.6.33 dies on modprobe
From: Andrew Morton @ 2010-03-03 2:52 UTC (permalink / raw)
To: Américo Wang
Cc: M G Berberich, linux-kernel, Linux Kernel Network Developers
In-Reply-To: <2375c9f91002282022n29e83858jd8cadbb2e664b436@mail.gmail.com>
On Mon, 1 Mar 2010 12:22:59 +0800 Am__rico Wang <xiyou.wangcong@gmail.com> wrote:
>
> You snipped too much. The full backtrace is useful:
>
> BUG: unable to handle kernel paging request at ffffffffa001b57f
> IP: [<ffffffff811895db>] strcmp+0xb/0x30
> PGD 1498067 PUD 149c063 PMD 12daf2067 PTE 0
> Oops: 0000 [#1] SMP
> last sysfs file:
> /sys/devices/pci0000:00/0000:00:05.0/host0/target0:0:0/0:0:0:0/type
> CPU 1
> Pid: 1249, comm: modprobe Not tainted 2.6.33-bmg #1 M55S-S3/
> RIP: 0010:[<ffffffff811895db>] [<ffffffff811895db>] strcmp+0xb/0x30
> RSP: 0018:ffff88012ebe9e58 EFLAGS: 00010282
> RAX: 0000000000000070 RBX: ffff88012f8f4f00 RCX: 00000000ffffffff
> RDX: ffff88012f808800 RSI: ffffffffa001b57f RDI: ffff88012fab2420
> RBP: ffff88012ebe9e58 R08: 0000000000000000 R09: 0000000000000000
> R10: ffff8800284017c0 R11: dead000000200200 R12: ffff88012f9a29c8
> R13: ffff88012f8842a0 R14: ffffffffa001b57f R15: 000000000081c050
> FS: 00007f16bd8916f0(0000) GS:ffff880028280000(0000) knlGS:0000000000000000
> CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> CR2: ffffffffa001b57f CR3: 000000012da7c000 CR4: 00000000000006e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> Process modprobe (pid: 1249, threadinfo ffff88012ebe8000, task ffff88012edec0a0)
> Stack:
> ffff88012ebe9e88 ffffffff811852e8 ffffffffa0013080 ffffffffa00130e0
> <0> 000000000081e970 000000000081e970 ffff88012ebe9e98 ffffffff81236b87
> <0> ffff88012ebe9ed8 ffffffff81236ca7 0000000000000021 0000000000000021
> Call Trace:
> [<ffffffff811852e8>] kset_find_obj+0x38/0x80
> [<ffffffff81236b87>] driver_find+0x17/0x30
> [<ffffffff81236ca7>] driver_register+0x67/0x140
> [<ffffffff8119b771>] __pci_register_driver+0x51/0xd0
> [<ffffffffa0017000>] ? init_nic+0x0/0x20 [forcedeth]
> [<ffffffffa001701e>] init_nic+0x1e/0x20 [forcedeth]
>
>
It could be that some kobject on that list has become invalid (memory
was freed, module was unloaded, etc) and later code stumbled across the
now-invalid object on that list and then crashed.
What we can do to find this is to add a diagnostic each time an object
is registered, and a diagnostic each time kset_find_obj() looks at the
objects. Then we'll see which kobject caused the crash, then we can
look back and see where that kobject was registered from.
Something like this:
--- a/lib/kobject.c~a
+++ a/lib/kobject.c
@@ -717,6 +717,8 @@ int kset_register(struct kset *k)
return -EINVAL;
kset_init(k);
+ printk("kset_register:%p\n", &k->kobj);
+ dump_stack();
err = kobject_add_internal(&k->kobj);
if (err)
return err;
@@ -751,9 +753,12 @@ struct kobject *kset_find_obj(struct kse
spin_lock(&kset->list_lock);
list_for_each_entry(k, &kset->list, entry) {
- if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
- ret = kobject_get(k);
- break;
+ if (kobject_name(k)) {
+ printk("kset_find_obj:%p\n", k);
+ if (!strcmp(kobject_name(k), name)) {
+ ret = kobject_get(k);
+ break;
+ }
}
}
spin_unlock(&kset->list_lock);
_
This will generate a lot of output and we don't want to lose any of it.
I'd suggest setting up netconsole so all the output can be reliably
saved: Documentation/networking/netconsole.txt
Thanks.
^ permalink raw reply
* Re: Current wireless-testing breaks libpcap: mr_alen should be set
From: John W. Linville @ 2010-03-03 2:36 UTC (permalink / raw)
To: Pavel Roskin
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA,
tcpdump-workers-YE1jQ5a0g24KACXWX4p+q9i2O/JbrIOy, Jiri Pirko
In-Reply-To: <1267578048.14049.11.camel@mj>
On Tue, Mar 02, 2010 at 08:00:48PM -0500, Pavel Roskin wrote:
> Also, pulling bleeding edge stuff into wireless-testing before rc1
> appears to be either a mistake or a bad decision.
Feel free to use an earlier commit...
--
John W. Linville Someday the world will need a hero, and you
linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org might be all we have. Be ready.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC v2 00/10] snet: Security for NETwork syscalls
From: Tetsuo Handa @ 2010-03-03 1:56 UTC (permalink / raw)
To: sam
Cc: linux-kernel, netdev, netfilter-devel, hadi, kaber, zbr, nhorman,
root, linux-security-module
In-Reply-To: <1267561394-13626-1-git-send-email-sam@synack.fr>
Hello.
Regarding [RFC v2 02/10] Revert "lsm: Remove the socket_post_accept() hook"
@@ -1538,6 +1538,8 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
fd_install(newfd, newfile);
err = newfd;
+ security_socket_post_accept(sock, newsock);
+
out_put:
fput_light(sock->file, fput_needed);
out:
Please move security_socket_post_accept() to before fd_install().
Otherwise, other threads which share fd tables can use
security-informations-not-yet-updated accept()ed sockets.
Regarding [RFC v2 04/10] snet: introduce snet_core
+static __init int snet_init(void)
+{
+ int ret;
+
+ pr_debug("initializing: event_hash_size=%u "
+ "verdict_hash_size=%u verdict_delay=%usecs "
+ "default_policy=%s\n",
+ snet_evh_size, snet_vdh_size, snet_verdict_delay,
+ snet_verdict_name(snet_verdict_policy));
Why not to stop here if snet_evh_size == 0 or snet_vdh_size == 0 in order to
avoid "division by 0".
Regarding [RFC v2 05/10] snet: introduce snet_event
+static rwlock_t snet_evh_lock = __RW_LOCK_UNLOCKED();
You can use "static DEFINE_RWLOCK(snet_evh_lock);".
+int snet_event_is_registered(const enum snet_syscall syscall, const u8 protocol)
Maybe rcu_read_lock() is better than rw spinlock because this function is
frequently called.
Regarding [RFC v2 06/10] snet: introduce snet_hooks
+ if ((verdict = snet_ticket_check(&info)) != SNET_VERDICT_NONE)
Please avoid assignment in "if" statement, as scripts/checkpatch.pl suggests.
Regarding [RFC v2 09/10] snet: introduce snet_ticket
+enum snet_verdict snet_ticket_check(struct snet_info *info)
+{
+ struct snet_ticket *st = NULL;
+ unsigned int h = 0, verdict = SNET_VERDICT_NONE;
+ struct list_head *l = NULL;
+ struct snet_task_security *tsec = NULL;
+
+ if (snet_ticket_mode == SNET_TICKET_OFF)
+ goto out;
+
+ tsec = (struct snet_task_security*) current_security();
+
+ h = jhash_2words(info->syscall, info->protocol, 0) % HSIZE;
+ l = &tsec->hash[h];
+
+ read_lock_bh(&tsec->lock);
Credentials are allocated for copy-on-write basis.
Sharing "tsec" among multiple "struct task_struct" is what you intended?
Regards.
^ permalink raw reply
* [PATCH] Bluetooth: Use single_open() for inquiry cache within debugfs
From: Marcel Holtmann @ 2010-03-03 1:48 UTC (permalink / raw)
To: David Miller; +Cc: netdev
The inquiry cache information in debugfs should be using seq_file support
and not allocating memory on the stack for the string. Since the usage of
these information is really seldom, using single_open() for it is good
enough.
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
---
net/bluetooth/hci_sysfs.c | 41 ++++++++++++++++++++---------------------
1 files changed, 20 insertions(+), 21 deletions(-)
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 1a79a6c..cafb55b 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -3,6 +3,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -405,20 +406,11 @@ static struct device_type bt_host = {
.release = bt_host_release,
};
-static int inquiry_cache_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
+static int inquiry_cache_show(struct seq_file *f, void *p)
{
- struct hci_dev *hdev = file->private_data;
+ struct hci_dev *hdev = f->private;
struct inquiry_cache *cache = &hdev->inq_cache;
struct inquiry_entry *e;
- char buf[4096];
- int n = 0;
hci_dev_lock_bh(hdev);
@@ -426,23 +418,30 @@ static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf,
struct inquiry_data *data = &e->data;
bdaddr_t bdaddr;
baswap(&bdaddr, &data->bdaddr);
- n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
- batostr(&bdaddr),
- data->pscan_rep_mode, data->pscan_period_mode,
- data->pscan_mode, data->dev_class[2],
- data->dev_class[1], data->dev_class[0],
- __le16_to_cpu(data->clock_offset),
- data->rssi, data->ssp_mode, e->timestamp);
+ seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
+ batostr(&bdaddr),
+ data->pscan_rep_mode, data->pscan_period_mode,
+ data->pscan_mode, data->dev_class[2],
+ data->dev_class[1], data->dev_class[0],
+ __le16_to_cpu(data->clock_offset),
+ data->rssi, data->ssp_mode, e->timestamp);
}
hci_dev_unlock_bh(hdev);
- return simple_read_from_buffer(userbuf, count, ppos, buf, n);
+ return 0;
+}
+
+static int inquiry_cache_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, inquiry_cache_show, inode->i_private);
}
static const struct file_operations inquiry_cache_fops = {
- .open = inquiry_cache_open,
- .read = inquiry_cache_read,
+ .open = inquiry_cache_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
int hci_register_sysfs(struct hci_dev *hdev)
--
1.6.6.1
^ permalink raw reply related
* Re: KS8695: possible NAPI issue
From: figo zhang @ 2010-03-03 1:46 UTC (permalink / raw)
To: Dick Hollenbeck; +Cc: Yegor Yefremov, netdev, zealcook
In-Reply-To: <4B8D1C02.1010204@softplc.com>
2010/3/2 Dick Hollenbeck <dick@softplc.com>:
> Yegor Yefremov wrote:
>>
>> I'm using 2.6.33 kernel and I noticed such a strange behavior:
>>
>> after system start I transfer one file via netcat from my development
>> host, after this transfer the network is not functioning i.e. no pings
>> possible etc.
>>
>> To narrow down the problem I checked out this commit
>>
>> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=451f14439847db302e5104c44458b2dbb4b1829d.
>> Till here the network driver is functioning as intended, but after
>> NAPI introduction I have this issue. With latest git-pull of "Linus'
>> kernel tree" I can't even ping right after the systems start.
>>
>> Any Ideas? What am I missing?
>>
>
> No idea, although I am using the same ARM chip, my kernel is at 2.6.30.5,
> and except for this occasional loss of connection I get, the ethernet driver
> seems to work better than what you are reporting.
from linux-2.6.32, this ethernet driver have add NAPI support, would
you like to
try using this version?
^ permalink raw reply
* Re: linux-next: Tree for March 1 (bluetooth/hci_sysfs)
From: Marcel Holtmann @ 2010-03-03 1:23 UTC (permalink / raw)
To: David Miller
Cc: sfr, randy.dunlap, linux-next, linux-kernel, linux-bluetooth,
netdev
In-Reply-To: <20100301.181415.266447389.davem@davemloft.net>
Hi Dave,
> >> static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf,
> >> size_t count, loff_t *ppos)
> >> {
> >> struct hci_dev *hdev = file->private_data;
> >> struct inquiry_cache *cache = &hdev->inq_cache;
> >> struct inquiry_entry *e;
> >> char buf[4096]; // <<<<<<<<<<<<<<<<<<<<<<<<<<< huh? don't do that on stack.
> >> int n = 0;
> >
> > Dave Miller is following up on that.
>
> This looks like a job for.... SEQ FILE! :-)
>
> I'm testing the following fix.
I have a working and tested patch that uses single_open(). Will send a
patch with commit message and everything in a bit so you can apply it.
Regards
Marcel
^ permalink raw reply
* Current wireless-testing breaks libpcap: mr_alen should be set
From: Pavel Roskin @ 2010-03-03 1:00 UTC (permalink / raw)
To: linux-wireless, netdev, tcpdump-workers; +Cc: Jiri Pirko
Hello!
The current wireless-testing appears to have some non-wireless bits from
the upcoming Linux 2.6.34. As a result, libpcap and all capture
programs that use it are broken.
This patch to libpcap helps:
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -1563,6 +1563,7 @@ live_open_new(pcap_t *handle, const char
memset(&mr, 0, sizeof(mr));
mr.mr_ifindex = handle->md.ifindex;
mr.mr_type = PACKET_MR_PROMISC;
+ mr.mr_alen = 6;
if (setsockopt(sock_fd, SOL_PACKET,
PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1)
{
libpcap git doesn't have the fix yet.
The breakage must be coming from the commit 914c8ad2 by Jiri Pirko to
net/packet/af_packet.c
I think it's very unhelpful to introduce patches that break significant
userspace functionality without giving the affected programs an advance
warning.
Also, pulling bleeding edge stuff into wireless-testing before rc1
appears to be either a mistake or a bad decision.
Sorry for cross-post, but it's an urgent issue. Repliers are encouraged
to trim the recipient list as necessary.
--
Regards,
Pavel Roskin
^ permalink raw reply
* Re: 2.6.33 problems
From: Tejun Heo @ 2010-03-03 0:56 UTC (permalink / raw)
To: Andrew Morton; +Cc: werner, linux-kernel, netdev
In-Reply-To: <20100302135032.e3d11bbf.akpm@linux-foundation.org>
Hello,
On 03/03/2010 06:50 AM, Andrew Morton wrote:
> On Sat, 27 Feb 2010 14:09:11 -0300 (GFT)
> werner@guyane.dyn-o-saur.com wrote:
>
>> For better error searching / correction, I add below the whole syslog.
>>
>> This is refered to 2.6.33 published (without patchs)
>>
>> This are different errors.
>>
>> The most of them exists since 2.6.33-rc1 or appr. -rc5.
>>
>> I posted here already the whole syslog.bz2 but nobody toke care.
>>
>> the boot_vga error occurs only after I start the grafics mode. It's the mainboard's embedded nvidia grafics. I use the vesa framebuffer driver of X 1.8
>>
>> the int6_init error occurs also in text mode. I think it have something to do with internet.
>>
>> Also the printk errors occur only when start the computer in the grafics mode, but not when starting it in the text mode.
>>
>> Below is also the kernel config. Its the same like since -rc7 (but the errors are also the same)
Hmmmm... it seems like the percpu allocator failed to allocate space
for a new chunk in the vmalloc area. Looking through the config.
Hmmm, w/ 3G split, there should be enough vmalloc area. Strange.
Does kernel parameter "percpu_alloc=page" make the machine boot? If
so, can you please post the output of dmesg right after boot?
Thanks.
--
tejun
^ permalink raw reply
* Re: [RFC PATCH]xfrm: fix perpetual bundles
From: jamal @ 2010-03-03 0:47 UTC (permalink / raw)
To: Steffen Klassert
Cc: Herbert Xu, davem, kaber, yoshfuji, nakam, eric.dumazet, netdev
In-Reply-To: <20100302140631.GD20508@secunet.com>
> Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
tested - Looks good.
Acked-by: Jamal Hadi Salim <hadi@cyberus.ca>
cheers,
jamal
^ permalink raw reply
* Re: [RFC][PATCH] ns: Syscalls for better namespace sharing control.
From: Eric W. Biederman @ 2010-03-03 0:46 UTC (permalink / raw)
To: Sukadev Bhattiprolu
Cc: Pavel Emelyanov, Daniel Lezcano, Linux Netdev List, containers,
Netfilter Development Mailinglist, Ben Greear
In-Reply-To: <20100303000743.GA13744@us.ibm.com>
Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> writes:
> Eric W. Biederman [ebiederm@xmission.com] wrote:
> |
> | I think replacing a struct pid for another struct pid allocated in
> | descendant pid_namespace (but has all of the same struct upid values
> | as the first struct pid) is a disastrous idea. It destroys the
>
> True. Sorry, I did not mean we would need a new 'struct pid' for an
> existing process. I think we talked earlier of finding a way of attaching
> additional pid numbers to the same struct pid.
I just played with this and if you make the semantics of unshare(CLONE_NEWPID)
to be that you become the idle task aka pid 0, and not the init task pid 1 the
implementation is trivial.
Eric
----
arch/powerpc/platforms/cell/spufs/sched.c | 2 +-
arch/um/drivers/mconsole_kern.c | 2 +-
fs/proc/root.c | 2 +-
init/main.c | 9 ---------
kernel/cgroup.c | 2 +-
kernel/fork.c | 16 +++++++++++++---
kernel/nsproxy.c | 2 +-
kernel/perf_event.c | 2 +-
kernel/pid.c | 8 ++++----
kernel/signal.c | 9 ++++-----
kernel/sysctl_binary.c | 2 +-
11 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index 4678078..b7f2026 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -1094,7 +1094,7 @@ static int show_spu_loadavg(struct seq_file *s, void *private)
LOAD_INT(c), LOAD_FRAC(c),
count_active_contexts(),
atomic_read(&nr_spu_contexts),
- current->nsproxy->pid_ns->last_pid);
+ task_active_pid_ns(current)->last_pid);
return 0;
}
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 3b3c366..4e6985e 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -125,7 +125,7 @@ void mconsole_log(struct mc_request *req)
void mconsole_proc(struct mc_request *req)
{
struct nameidata nd;
- struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
+ struct vfsmount *mnt = task_active_pid_ns(current)->proc_mnt;
struct file *file;
int n, err;
char *ptr = req->request.data, *buf;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index b080b79..fbcd3f8 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -57,7 +57,7 @@ static int proc_get_sb(struct file_system_type *fs_type,
if (flags & MS_KERNMOUNT)
ns = (struct pid_namespace *)data;
else
- ns = current->nsproxy->pid_ns;
+ ns = task_active_pid_ns(current);
sb = sget(fs_type, proc_test_super, proc_set_super, ns);
if (IS_ERR(sb))
diff --git a/init/main.c b/init/main.c
index 4cb47a1..67e40fc 100644
--- a/init/main.c
+++ b/init/main.c
@@ -851,15 +851,6 @@ static int __init kernel_init(void * unused)
* init can run on any cpu.
*/
set_cpus_allowed_ptr(current, cpu_all_mask);
- /*
- * Tell the world that we're going to be the grim
- * reaper of innocent orphaned children.
- *
- * We don't want people to have to make incorrect
- * assumptions about where in the task array this
- * can be found.
- */
- init_pid_ns.child_reaper = current;
cad_pid = task_pid(current);
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index aa3bee5..737d2eb 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2453,7 +2453,7 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp,
{
struct cgroup_pidlist *l;
/* don't need task_nsproxy() if we're looking at ourself */
- struct pid_namespace *ns = get_pid_ns(current->nsproxy->pid_ns);
+ struct pid_namespace *ns = get_pid_ns(task_active_pid_ns(current));
/*
* We can't drop the pidlist_mutex before taking the l->mutex in case
* the last ref-holder is trying to remove l from the list at the same
diff --git a/kernel/fork.c b/kernel/fork.c
index f88bd98..832c035 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1172,7 +1172,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
if (!pid)
goto bad_fork_cleanup_io;
- if (clone_flags & CLONE_NEWPID) {
+ if (pid->numbers[pid->level].nr == 1) {
retval = pid_ns_prepare_proc(p->nsproxy->pid_ns);
if (retval < 0)
goto bad_fork_free_pid;
@@ -1279,7 +1279,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
tracehook_finish_clone(p, clone_flags, trace);
if (thread_group_leader(p)) {
- if (clone_flags & CLONE_NEWPID)
+ if (pid->numbers[pid->level].nr == 1)
p->nsproxy->pid_ns->child_reaper = p;
p->signal->leader_pid = pid;
@@ -1539,10 +1539,19 @@ static void check_unshare_flags(unsigned long *flags_ptr)
*flags_ptr |= CLONE_THREAD;
/*
+ * If unsharing the pid namespace and the task was created
+ * using CLONE_THREAD, then must unshare the thread.
+ */
+ if ((*flags_ptr & CLONE_NEWPID) &&
+ (atomic_read(¤t->signal->count) > 1))
+ *flags_ptr |= CLONE_THREAD;
+
+ /*
* If unsharing namespace, must also unshare filesystem information.
*/
if (*flags_ptr & CLONE_NEWNS)
*flags_ptr |= CLONE_FS;
+
}
/*
@@ -1647,7 +1656,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
err = -EINVAL;
if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
- CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
+ CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET|
+ CLONE_NEWPID))
goto bad_unshare_out;
/*
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index e3be4ef..1d023d5 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -173,7 +173,7 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
int err = 0;
if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
- CLONE_NEWNET)))
+ CLONE_NEWNET | CLONE_NEWPID)))
return 0;
if (!capable(CAP_SYS_ADMIN))
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 2ae7409..74865cd 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -4436,7 +4436,7 @@ perf_event_alloc(struct perf_event_attr *attr,
event->parent = parent_event;
- event->ns = get_pid_ns(current->nsproxy->pid_ns);
+ event->ns = get_pid_ns(task_active_pid_ns(current));
event->id = atomic64_inc_return(&perf_event_id);
event->state = PERF_EVENT_STATE_INACTIVE;
diff --git a/kernel/pid.c b/kernel/pid.c
index 2e17c9c..6b64a82 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -305,7 +305,7 @@ EXPORT_SYMBOL_GPL(find_pid_ns);
struct pid *find_vpid(int nr)
{
- return find_pid_ns(nr, current->nsproxy->pid_ns);
+ return find_pid_ns(nr, task_active_pid_ns(current));
}
EXPORT_SYMBOL_GPL(find_vpid);
@@ -385,7 +385,7 @@ struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns)
struct task_struct *find_task_by_vpid(pid_t vnr)
{
- return find_task_by_pid_ns(vnr, current->nsproxy->pid_ns);
+ return find_task_by_pid_ns(vnr, task_active_pid_ns(current));
}
struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
@@ -437,7 +437,7 @@ pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns)
pid_t pid_vnr(struct pid *pid)
{
- return pid_nr_ns(pid, current->nsproxy->pid_ns);
+ return pid_nr_ns(pid, task_active_pid_ns(current));
}
EXPORT_SYMBOL_GPL(pid_vnr);
@@ -448,7 +448,7 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
rcu_read_lock();
if (!ns)
- ns = current->nsproxy->pid_ns;
+ ns = task_active_pid_ns(current);
if (likely(pid_alive(task))) {
if (type != PIDTYPE_PID)
task = task->group_leader;
diff --git a/kernel/signal.c b/kernel/signal.c
index 934ae5e..885b699 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1438,16 +1438,15 @@ int do_notify_parent(struct task_struct *tsk, int sig)
* we are under tasklist_lock here so our parent is tied to
* us and cannot exit and release its namespace.
*
- * the only it can is to switch its nsproxy with sys_unshare,
- * bu uncharing pid namespaces is not allowed, so we'll always
- * see relevant namespace
+ * The only it can is to switch its nsproxy with sys_unshare,
+ * but we use the pid_namespace for task_pid which never changes.
*
* write_lock() currently calls preempt_disable() which is the
* same as rcu_read_lock(), but according to Oleg, this is not
* correct to rely on this
*/
rcu_read_lock();
- info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns);
+ info.si_pid = task_pid_nr_ns(tsk, task_active_pid_ns(tsk->parent));
info.si_uid = __task_cred(tsk)->uid;
rcu_read_unlock();
@@ -1518,7 +1517,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
* see comment in do_notify_parent() abot the following 3 lines
*/
rcu_read_lock();
- info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns);
+ info.si_pid = task_pid_nr_ns(tsk, task_active_pid_ns(parent));
info.si_uid = __task_cred(tsk)->uid;
rcu_read_unlock();
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index 8f5d16e..1e4da59 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -1356,7 +1356,7 @@ static ssize_t binary_sysctl(const int *name, int nlen,
goto out_putname;
}
- mnt = current->nsproxy->pid_ns->proc_mnt;
+ mnt = task_active_pid_ns(current)->proc_mnt;
result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd);
if (result)
goto out_putname;
^ permalink raw reply related
* Re: [RFC v2 03/10] snet: introduce security/snet, Makefile and Kconfig changes
From: Samir Bellabes @ 2010-03-03 0:23 UTC (permalink / raw)
To: Greg KH
Cc: linux-security-module, linux-kernel, netdev, netfilter-devel,
jamal, Patrick McHardy, Evgeniy Polyakov, Neil Horman,
Grzegorz Nosek
In-Reply-To: <20100303000347.GA3017@kroah.com>
Greg KH <greg@kroah.com> writes:
> On Tue, Mar 02, 2010 at 09:23:07PM +0100, Samir Bellabes wrote:
>> this patch creates folder security/snet and adds changes for Kconfig and Makefile
>
> But it breaks the build, as you are referring to files here that are not
> present yet. Please put this at the end of your patch series to make
> the tree always build for every individual patch.
yes, sure.
thank you Greg
sam
^ permalink raw reply
* [RFC][ PATCH 3/3] vhost-net: Add mergeable RX buffer support to vhost-net
From: David Stevens @ 2010-03-03 0:20 UTC (permalink / raw)
To: mst, rusty; +Cc: netdev, kvm, virtualization
[-- Attachment #1: Type: text/plain, Size: 7770 bytes --]
This patch glues them all together and makes sure we
notify whenever we don't have enough buffers to receive
a max-sized packet, and adds the feature bit.
Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
diff -ruN net-next-p2/drivers/vhost/net.c net-next-p3/drivers/vhost/net.c
--- net-next-p2/drivers/vhost/net.c 2010-03-02 13:01:34.000000000
-0800
+++ net-next-p3/drivers/vhost/net.c 2010-03-02 15:25:15.000000000
-0800
@@ -54,26 +54,6 @@
enum vhost_net_poll_state tx_poll_state;
};
-/* Pop first len bytes from iovec. Return number of segments used. */
-static int move_iovec_hdr(struct iovec *from, struct iovec *to,
- size_t len, int iov_count)
-{
- int seg = 0;
- size_t size;
- while (len && seg < iov_count) {
- size = min(from->iov_len, len);
- to->iov_base = from->iov_base;
- to->iov_len = size;
- from->iov_len -= size;
- from->iov_base += size;
- len -= size;
- ++from;
- ++to;
- ++seg;
- }
- return seg;
-}
-
/* Caller must have TX VQ lock */
static void tx_poll_stop(struct vhost_net *net)
{
@@ -97,7 +77,7 @@
static void handle_tx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
- unsigned out, in, s;
+ unsigned out, in;
struct iovec head;
struct msghdr msg = {
.msg_name = NULL,
@@ -110,6 +90,7 @@
size_t len, total_len = 0;
int err, wmem;
struct socket *sock = rcu_dereference(vq->private_data);
+
if (!sock)
return;
@@ -166,11 +147,11 @@
/* Skip header. TODO: support TSO. */
msg.msg_iovlen = out;
head.iov_len = len = iov_length(vq->iov, out);
+
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for TX: "
- "%zd expected %zd\n",
- len, vq->guest_hlen);
+ "%zd expected %zd\n", len, vq->guest_hlen);
break;
}
/* TODO: Check specific error and bomb out unless ENOBUFS?
*/
@@ -214,7 +195,7 @@
static void handle_rx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
- unsigned in, log, s;
+ unsigned in, log;
struct vhost_log *vq_log;
struct msghdr msg = {
.msg_name = NULL,
@@ -245,30 +226,36 @@
if (!headcount) {
vhost_enable_notify(vq);
break;
- }
+ } else if (vq->maxheadcount < headcount)
+ vq->maxheadcount = headcount;
/* Skip header. TODO: support TSO/mergeable rx buffers. */
msg.msg_iovlen = in;
len = iov_length(vq->iov, in);
-
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for RX: "
- "%zd expected %zd\n",
- len, vq->guest_hlen);
+ "%zd expected %zd\n", len, vq->guest_hlen);
break;
}
err = sock->ops->recvmsg(NULL, sock, &msg,
len, MSG_DONTWAIT | MSG_TRUNC);
- /* TODO: Check specific error and bomb out unless EAGAIN?
*/
if (err < 0) {
- vhost_discard(vq, 1);
+ vhost_discard(vq, headcount);
break;
}
/* TODO: Should check and handle checksum. */
+ if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF))
{
+ struct virtio_net_hdr_mrg_rxbuf *vhdr =
+ (struct virtio_net_hdr_mrg_rxbuf *)
+ vq->iov[0].iov_base;
+ /* add num_bufs */
+ vq->iov[0].iov_len = vq->guest_hlen;
+ vhdr->num_buffers = headcount;
+ }
if (err > len) {
pr_err("Discarded truncated rx packet: "
" len %d > %zd\n", err, len);
- vhost_discard(vq, 1);
+ vhost_discard(vq, headcount);
continue;
}
len = err;
@@ -573,8 +560,6 @@
static int vhost_net_set_features(struct vhost_net *n, u64 features)
{
- size_t hdr_size = features & (1 << VHOST_NET_F_VIRTIO_NET_HDR) ?
- sizeof(struct virtio_net_hdr) : 0;
int i;
mutex_lock(&n->dev.mutex);
if ((features & (1 << VHOST_F_LOG_ALL)) &&
diff -ruN net-next-p2/drivers/vhost/vhost.c
net-next-p3/drivers/vhost/vhost.c
--- net-next-p2/drivers/vhost/vhost.c 2010-03-02 12:53:02.000000000
-0800
+++ net-next-p3/drivers/vhost/vhost.c 2010-03-02 15:24:50.000000000
-0800
@@ -115,6 +115,7 @@
vq->log_addr = -1ull;
vq->guest_hlen = 0;
vq->sock_hlen = 0;
+ vq->maxheadcount = 0;
vq->private_data = NULL;
vq->log_base = NULL;
vq->error_ctx = NULL;
@@ -410,6 +411,7 @@
vq->last_avail_idx = s.num;
/* Forget the cached index value. */
vq->avail_idx = vq->last_avail_idx;
+ vq->maxheadcount = 0;
break;
case VHOST_GET_VRING_BASE:
s.index = idx;
@@ -1114,10 +1116,23 @@
return 0;
}
+int vhost_available(struct vhost_virtqueue *vq)
+{
+ int avail;
+
+ if (!vq->maxheadcount) /* haven't got any yet */
+ return 1;
+ avail = vq->avail_idx - vq->last_avail_idx;
+ if (avail < 0)
+ avail += 0x10000; /* wrapped */
+ return avail;
+}
+
/* This actually signals the guest, using eventfd. */
void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)
{
__u16 flags = 0;
+
if (get_user(flags, &vq->avail->flags)) {
vq_err(vq, "Failed to get flags");
return;
@@ -1125,7 +1140,7 @@
/* If they don't want an interrupt, don't signal, unless empty. */
if ((flags & VRING_AVAIL_F_NO_INTERRUPT) &&
- (vq->avail_idx != vq->last_avail_idx ||
+ (vhost_available(vq) > vq->maxheadcount ||
!vhost_has_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY)))
return;
diff -ruN net-next-p2/drivers/vhost/vhost.h
net-next-p3/drivers/vhost/vhost.h
--- net-next-p2/drivers/vhost/vhost.h 2010-03-02 13:02:03.000000000
-0800
+++ net-next-p3/drivers/vhost/vhost.h 2010-03-02 14:29:44.000000000
-0800
@@ -85,6 +85,7 @@
struct iovec iov[VHOST_NET_MAX_SG+1]; /* an extra for vnet hdr */
struct iovec heads[VHOST_NET_MAX_SG];
size_t guest_hlen, sock_hlen;
+ int maxheadcount;
/* We use a kind of RCU to access private pointer.
* All readers access it from workqueue, which makes it possible
to
* flush the workqueue instead of synchronize_rcu. Therefore
readers do
@@ -151,7 +152,8 @@
VHOST_FEATURES = (1 << VIRTIO_F_NOTIFY_ON_EMPTY) |
(1 << VIRTIO_RING_F_INDIRECT_DESC) |
(1 << VHOST_F_LOG_ALL) |
- (1 << VHOST_NET_F_VIRTIO_NET_HDR),
+ (1 << VHOST_NET_F_VIRTIO_NET_HDR) |
+ (1 << VIRTIO_NET_F_MRG_RXBUF),
};
static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
[-- Attachment #2: MRXB3.patch --]
[-- Type: application/octet-stream, Size: 5852 bytes --]
diff -ruN net-next-p2/drivers/vhost/net.c net-next-p3/drivers/vhost/net.c
--- net-next-p2/drivers/vhost/net.c 2010-03-02 13:01:34.000000000 -0800
+++ net-next-p3/drivers/vhost/net.c 2010-03-02 15:25:15.000000000 -0800
@@ -54,26 +54,6 @@
enum vhost_net_poll_state tx_poll_state;
};
-/* Pop first len bytes from iovec. Return number of segments used. */
-static int move_iovec_hdr(struct iovec *from, struct iovec *to,
- size_t len, int iov_count)
-{
- int seg = 0;
- size_t size;
- while (len && seg < iov_count) {
- size = min(from->iov_len, len);
- to->iov_base = from->iov_base;
- to->iov_len = size;
- from->iov_len -= size;
- from->iov_base += size;
- len -= size;
- ++from;
- ++to;
- ++seg;
- }
- return seg;
-}
-
/* Caller must have TX VQ lock */
static void tx_poll_stop(struct vhost_net *net)
{
@@ -97,7 +77,7 @@
static void handle_tx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
- unsigned out, in, s;
+ unsigned out, in;
struct iovec head;
struct msghdr msg = {
.msg_name = NULL,
@@ -110,6 +90,7 @@
size_t len, total_len = 0;
int err, wmem;
struct socket *sock = rcu_dereference(vq->private_data);
+
if (!sock)
return;
@@ -166,11 +147,11 @@
/* Skip header. TODO: support TSO. */
msg.msg_iovlen = out;
head.iov_len = len = iov_length(vq->iov, out);
+
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for TX: "
- "%zd expected %zd\n",
- len, vq->guest_hlen);
+ "%zd expected %zd\n", len, vq->guest_hlen);
break;
}
/* TODO: Check specific error and bomb out unless ENOBUFS? */
@@ -214,7 +195,7 @@
static void handle_rx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
- unsigned in, log, s;
+ unsigned in, log;
struct vhost_log *vq_log;
struct msghdr msg = {
.msg_name = NULL,
@@ -245,30 +226,36 @@
if (!headcount) {
vhost_enable_notify(vq);
break;
- }
+ } else if (vq->maxheadcount < headcount)
+ vq->maxheadcount = headcount;
/* Skip header. TODO: support TSO/mergeable rx buffers. */
msg.msg_iovlen = in;
len = iov_length(vq->iov, in);
-
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for RX: "
- "%zd expected %zd\n",
- len, vq->guest_hlen);
+ "%zd expected %zd\n", len, vq->guest_hlen);
break;
}
err = sock->ops->recvmsg(NULL, sock, &msg,
len, MSG_DONTWAIT | MSG_TRUNC);
- /* TODO: Check specific error and bomb out unless EAGAIN? */
if (err < 0) {
- vhost_discard(vq, 1);
+ vhost_discard(vq, headcount);
break;
}
/* TODO: Should check and handle checksum. */
+ if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF)) {
+ struct virtio_net_hdr_mrg_rxbuf *vhdr =
+ (struct virtio_net_hdr_mrg_rxbuf *)
+ vq->iov[0].iov_base;
+ /* add num_bufs */
+ vq->iov[0].iov_len = vq->guest_hlen;
+ vhdr->num_buffers = headcount;
+ }
if (err > len) {
pr_err("Discarded truncated rx packet: "
" len %d > %zd\n", err, len);
- vhost_discard(vq, 1);
+ vhost_discard(vq, headcount);
continue;
}
len = err;
@@ -573,8 +560,6 @@
static int vhost_net_set_features(struct vhost_net *n, u64 features)
{
- size_t hdr_size = features & (1 << VHOST_NET_F_VIRTIO_NET_HDR) ?
- sizeof(struct virtio_net_hdr) : 0;
int i;
mutex_lock(&n->dev.mutex);
if ((features & (1 << VHOST_F_LOG_ALL)) &&
diff -ruN net-next-p2/drivers/vhost/vhost.c net-next-p3/drivers/vhost/vhost.c
--- net-next-p2/drivers/vhost/vhost.c 2010-03-02 12:53:02.000000000 -0800
+++ net-next-p3/drivers/vhost/vhost.c 2010-03-02 15:24:50.000000000 -0800
@@ -115,6 +115,7 @@
vq->log_addr = -1ull;
vq->guest_hlen = 0;
vq->sock_hlen = 0;
+ vq->maxheadcount = 0;
vq->private_data = NULL;
vq->log_base = NULL;
vq->error_ctx = NULL;
@@ -410,6 +411,7 @@
vq->last_avail_idx = s.num;
/* Forget the cached index value. */
vq->avail_idx = vq->last_avail_idx;
+ vq->maxheadcount = 0;
break;
case VHOST_GET_VRING_BASE:
s.index = idx;
@@ -1114,10 +1116,23 @@
return 0;
}
+int vhost_available(struct vhost_virtqueue *vq)
+{
+ int avail;
+
+ if (!vq->maxheadcount) /* haven't got any yet */
+ return 1;
+ avail = vq->avail_idx - vq->last_avail_idx;
+ if (avail < 0)
+ avail += 0x10000; /* wrapped */
+ return avail;
+}
+
/* This actually signals the guest, using eventfd. */
void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)
{
__u16 flags = 0;
+
if (get_user(flags, &vq->avail->flags)) {
vq_err(vq, "Failed to get flags");
return;
@@ -1125,7 +1140,7 @@
/* If they don't want an interrupt, don't signal, unless empty. */
if ((flags & VRING_AVAIL_F_NO_INTERRUPT) &&
- (vq->avail_idx != vq->last_avail_idx ||
+ (vhost_available(vq) > vq->maxheadcount ||
!vhost_has_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY)))
return;
diff -ruN net-next-p2/drivers/vhost/vhost.h net-next-p3/drivers/vhost/vhost.h
--- net-next-p2/drivers/vhost/vhost.h 2010-03-02 13:02:03.000000000 -0800
+++ net-next-p3/drivers/vhost/vhost.h 2010-03-02 14:29:44.000000000 -0800
@@ -85,6 +85,7 @@
struct iovec iov[VHOST_NET_MAX_SG+1]; /* an extra for vnet hdr */
struct iovec heads[VHOST_NET_MAX_SG];
size_t guest_hlen, sock_hlen;
+ int maxheadcount;
/* We use a kind of RCU to access private pointer.
* All readers access it from workqueue, which makes it possible to
* flush the workqueue instead of synchronize_rcu. Therefore readers do
@@ -151,7 +152,8 @@
VHOST_FEATURES = (1 << VIRTIO_F_NOTIFY_ON_EMPTY) |
(1 << VIRTIO_RING_F_INDIRECT_DESC) |
(1 << VHOST_F_LOG_ALL) |
- (1 << VHOST_NET_F_VIRTIO_NET_HDR),
+ (1 << VHOST_NET_F_VIRTIO_NET_HDR) |
+ (1 << VIRTIO_NET_F_MRG_RXBUF),
};
static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
^ permalink raw reply
* [RFC][ PATCH 1/3] vhost-net: support multiple buffer heads in receiver
From: David Stevens @ 2010-03-03 0:20 UTC (permalink / raw)
To: mst, rusty; +Cc: netdev, kvm, virtualization
[-- Attachment #1: Type: text/plain, Size: 12556 bytes --]
This patch generalizes buffer handling functions to
support multiple buffer heads.
In-line for viewing, attached for applying.
Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
diff -ruN net-next-p0/drivers/vhost/net.c net-next-p1/drivers/vhost/net.c
--- net-next-p0/drivers/vhost/net.c 2010-02-24 12:59:24.000000000
-0800
+++ net-next-p1/drivers/vhost/net.c 2010-03-01 11:44:22.000000000
-0800
@@ -97,7 +97,8 @@
static void handle_tx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
- unsigned head, out, in, s;
+ unsigned out, in, s;
+ struct iovec head;
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
@@ -126,12 +127,10 @@
hdr_size = vq->hdr_size;
for (;;) {
- head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
- ARRAY_SIZE(vq->iov),
- &out, &in,
- NULL, NULL);
+ head.iov_base = (void *)vhost_get_vq_desc(&net->dev, vq,
+ vq->iov, ARRAY_SIZE(vq->iov), &out, &in, NULL,
NULL);
/* Nothing new? Wait for eventfd to tell us they
refilled. */
- if (head == vq->num) {
+ if (head.iov_base == (void *)vq->num) {
wmem = atomic_read(&sock->sk->sk_wmem_alloc);
if (wmem >= sock->sk->sk_sndbuf * 3 / 4) {
tx_poll_start(net, sock);
@@ -152,7 +151,7 @@
/* Skip header. TODO: support TSO. */
s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, out);
msg.msg_iovlen = out;
- len = iov_length(vq->iov, out);
+ head.iov_len = len = iov_length(vq->iov, out);
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for TX: "
@@ -163,14 +162,14 @@
/* TODO: Check specific error and bomb out unless ENOBUFS?
*/
err = sock->ops->sendmsg(NULL, sock, &msg, len);
if (unlikely(err < 0)) {
- vhost_discard_vq_desc(vq);
+ vhost_discard(vq, 1);
tx_poll_start(net, sock);
break;
}
if (err != len)
pr_err("Truncated TX packet: "
" len %d != %zd\n", err, len);
- vhost_add_used_and_signal(&net->dev, vq, head, 0);
+ vhost_add_used_and_signal(&net->dev, vq, &head, 1);
total_len += len;
if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
vhost_poll_queue(&vq->poll);
@@ -182,12 +181,22 @@
unuse_mm(net->dev.mm);
}
+static int skb_head_len(struct sk_buff_head *skq)
+{
+ struct sk_buff *head;
+
+ head = skb_peek(skq);
+ if (head)
+ return head->len;
+ return 0;
+}
+
/* Expects to be always run from workqueue - which acts as
* read-size critical section for our kind of RCU. */
static void handle_rx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
- unsigned head, out, in, log, s;
+ unsigned in, log, s;
struct vhost_log *vq_log;
struct msghdr msg = {
.msg_name = NULL,
@@ -204,10 +213,11 @@
};
size_t len, total_len = 0;
- int err;
+ int err, headcount, datalen;
size_t hdr_size;
struct socket *sock = rcu_dereference(vq->private_data);
- if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
+
+ if (!sock || !skb_head_len(&sock->sk->sk_receive_queue))
return;
use_mm(net->dev.mm);
@@ -218,13 +228,10 @@
vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
vq->log : NULL;
- for (;;) {
- head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
- ARRAY_SIZE(vq->iov),
- &out, &in,
- vq_log, &log);
+ while ((datalen = skb_head_len(&sock->sk->sk_receive_queue))) {
+ headcount = vhost_get_heads(vq, datalen, &in, vq_log,
&log);
/* OK, now we need to know about added descriptors. */
- if (head == vq->num) {
+ if (!headcount) {
if (unlikely(vhost_enable_notify(vq))) {
/* They have slipped one in as we were
* doing that: check again. */
@@ -235,13 +242,6 @@
* they refilled. */
break;
}
- /* We don't need to be notified again. */
- if (out) {
- vq_err(vq, "Unexpected descriptor format for RX: "
- "out %d, int %d\n",
- out, in);
- break;
- }
/* Skip header. TODO: support TSO/mergeable rx buffers. */
s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in);
msg.msg_iovlen = in;
@@ -257,14 +257,14 @@
len, MSG_DONTWAIT | MSG_TRUNC);
/* TODO: Check specific error and bomb out unless EAGAIN?
*/
if (err < 0) {
- vhost_discard_vq_desc(vq);
+ vhost_discard(vq, 1);
break;
}
/* TODO: Should check and handle checksum. */
if (err > len) {
pr_err("Discarded truncated rx packet: "
" len %d > %zd\n", err, len);
- vhost_discard_vq_desc(vq);
+ vhost_discard(vq, 1);
continue;
}
len = err;
@@ -275,7 +275,7 @@
break;
}
len += hdr_size;
- vhost_add_used_and_signal(&net->dev, vq, head, len);
+ vhost_add_used_and_signal(&net->dev, vq, vq->heads,
headcount);
if (unlikely(vq_log))
vhost_log_write(vq, vq_log, log, len);
total_len += len;
diff -ruN net-next-p0/drivers/vhost/vhost.c
net-next-p1/drivers/vhost/vhost.c
--- net-next-p0/drivers/vhost/vhost.c 2010-02-15 20:08:35.000000000
-0800
+++ net-next-p1/drivers/vhost/vhost.c 2010-03-01 11:44:06.000000000
-0800
@@ -848,6 +848,38 @@
return 0;
}
+unsigned vhost_get_heads(struct vhost_virtqueue *vq, int datalen, int
*iovcount,
+ struct vhost_log *log, unsigned int *log_num)
+{
+ struct iovec *heads = vq->heads;
+ int out, in;
+ int hc = 0;
+
+ while (datalen > 0) {
+ if (hc >= VHOST_NET_MAX_SG) {
+ vhost_discard(vq, hc);
+ return 0;
+ }
+ heads[hc].iov_base = (void *)vhost_get_vq_desc(vq->dev,
vq,
+ vq->iov, ARRAY_SIZE(vq->iov), &out, &in, log,
log_num);
+ if (heads[hc].iov_base == (void *)vq->num) {
+ vhost_discard(vq, hc);
+ return 0;
+ }
+ if (out || in <= 0) {
+ vq_err(vq, "unexpected descriptor format for RX: "
+ "out %d, in %d\n", out, in);
+ vhost_discard(vq, hc);
+ return 0;
+ }
+ heads[hc].iov_len = iov_length(vq->iov, in);
+ hc++;
+ datalen -= heads[hc].iov_len;
+ }
+ *iovcount = in;
+ return hc;
+}
+
/* This looks in the virtqueue and for the first available buffer, and
converts
* it to an iovec for convenient access. Since descriptors consist of
some
* number of output then some number of input descriptors, it's actually
two
@@ -973,31 +1005,32 @@
}
/* Reverse the effect of vhost_get_vq_desc. Useful for error handling. */
-void vhost_discard_vq_desc(struct vhost_virtqueue *vq)
+void vhost_discard(struct vhost_virtqueue *vq, int n)
{
- vq->last_avail_idx--;
+ vq->last_avail_idx -= n;
}
/* After we've used one of their buffers, we tell them about it. We'll
then
* want to notify the guest, using eventfd. */
-int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int
len)
+int vhost_add_used(struct vhost_virtqueue *vq, struct iovec *heads, int
count)
{
struct vring_used_elem *used;
+ int i;
- /* The virtqueue contains a ring of used buffers. Get a pointer
to the
- * next entry in that used ring. */
- used = &vq->used->ring[vq->last_used_idx % vq->num];
- if (put_user(head, &used->id)) {
- vq_err(vq, "Failed to write used id");
- return -EFAULT;
- }
- if (put_user(len, &used->len)) {
- vq_err(vq, "Failed to write used len");
- return -EFAULT;
+ for (i=0; i<count; i++, vq->last_used_idx++) {
+ used = &vq->used->ring[vq->last_used_idx % vq->num];
+ if (put_user((unsigned)heads[i].iov_base, &used->id)) {
+ vq_err(vq, "Failed to write used id");
+ return -EFAULT;
+ }
+ if (put_user(heads[i].iov_len, &used->len)) {
+ vq_err(vq, "Failed to write used len");
+ return -EFAULT;
+ }
}
/* Make sure buffer is written before we update index. */
smp_wmb();
- if (put_user(vq->last_used_idx + 1, &vq->used->idx)) {
+ if (put_user(vq->last_used_idx, &vq->used->idx)) {
vq_err(vq, "Failed to increment used idx");
return -EFAULT;
}
@@ -1011,7 +1044,6 @@
if (vq->log_ctx)
eventfd_signal(vq->log_ctx, 1);
}
- vq->last_used_idx++;
return 0;
}
@@ -1038,9 +1070,9 @@
/* And here's the combo meal deal. Supersize me! */
void vhost_add_used_and_signal(struct vhost_dev *dev,
struct vhost_virtqueue *vq,
- unsigned int head, int len)
+ struct iovec *heads, int count)
{
- vhost_add_used(vq, head, len);
+ vhost_add_used(vq, heads, count);
vhost_signal(dev, vq);
}
diff -ruN net-next-p0/drivers/vhost/vhost.h
net-next-p1/drivers/vhost/vhost.h
--- net-next-p0/drivers/vhost/vhost.h 2010-02-15 20:08:35.000000000
-0800
+++ net-next-p1/drivers/vhost/vhost.h 2010-03-01 11:42:18.000000000
-0800
@@ -84,6 +84,7 @@
struct iovec indirect[VHOST_NET_MAX_SG];
struct iovec iov[VHOST_NET_MAX_SG];
struct iovec hdr[VHOST_NET_MAX_SG];
+ struct iovec heads[VHOST_NET_MAX_SG];
size_t hdr_size;
/* We use a kind of RCU to access private pointer.
* All readers access it from workqueue, which makes it possible
to
@@ -120,16 +121,18 @@
int vhost_vq_access_ok(struct vhost_virtqueue *vq);
int vhost_log_access_ok(struct vhost_dev *);
+unsigned vhost_get_heads(struct vhost_virtqueue *, int datalen, int
*iovcount,
+ struct vhost_log *log, unsigned int *log_num);
unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
struct iovec iov[], unsigned int iov_count,
unsigned int *out_num, unsigned int *in_num,
struct vhost_log *log, unsigned int *log_num);
-void vhost_discard_vq_desc(struct vhost_virtqueue *);
+void vhost_discard(struct vhost_virtqueue *, int);
-int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
-void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
+int vhost_add_used(struct vhost_virtqueue *, struct iovec *heads, int
count);
void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue
*,
- unsigned int head, int len);
+ struct iovec *heads, int count);
+void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
void vhost_disable_notify(struct vhost_virtqueue *);
bool vhost_enable_notify(struct vhost_virtqueue *);
[-- Attachment #2: MRXB1.patch --]
[-- Type: application/octet-stream, Size: 9612 bytes --]
diff -ruN net-next-p0/drivers/vhost/net.c net-next-p1/drivers/vhost/net.c
--- net-next-p0/drivers/vhost/net.c 2010-02-24 12:59:24.000000000 -0800
+++ net-next-p1/drivers/vhost/net.c 2010-03-01 11:44:22.000000000 -0800
@@ -97,7 +97,8 @@
static void handle_tx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
- unsigned head, out, in, s;
+ unsigned out, in, s;
+ struct iovec head;
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
@@ -126,12 +127,10 @@
hdr_size = vq->hdr_size;
for (;;) {
- head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
- ARRAY_SIZE(vq->iov),
- &out, &in,
- NULL, NULL);
+ head.iov_base = (void *)vhost_get_vq_desc(&net->dev, vq,
+ vq->iov, ARRAY_SIZE(vq->iov), &out, &in, NULL, NULL);
/* Nothing new? Wait for eventfd to tell us they refilled. */
- if (head == vq->num) {
+ if (head.iov_base == (void *)vq->num) {
wmem = atomic_read(&sock->sk->sk_wmem_alloc);
if (wmem >= sock->sk->sk_sndbuf * 3 / 4) {
tx_poll_start(net, sock);
@@ -152,7 +151,7 @@
/* Skip header. TODO: support TSO. */
s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, out);
msg.msg_iovlen = out;
- len = iov_length(vq->iov, out);
+ head.iov_len = len = iov_length(vq->iov, out);
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for TX: "
@@ -163,14 +162,14 @@
/* TODO: Check specific error and bomb out unless ENOBUFS? */
err = sock->ops->sendmsg(NULL, sock, &msg, len);
if (unlikely(err < 0)) {
- vhost_discard_vq_desc(vq);
+ vhost_discard(vq, 1);
tx_poll_start(net, sock);
break;
}
if (err != len)
pr_err("Truncated TX packet: "
" len %d != %zd\n", err, len);
- vhost_add_used_and_signal(&net->dev, vq, head, 0);
+ vhost_add_used_and_signal(&net->dev, vq, &head, 1);
total_len += len;
if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
vhost_poll_queue(&vq->poll);
@@ -182,12 +181,22 @@
unuse_mm(net->dev.mm);
}
+static int skb_head_len(struct sk_buff_head *skq)
+{
+ struct sk_buff *head;
+
+ head = skb_peek(skq);
+ if (head)
+ return head->len;
+ return 0;
+}
+
/* Expects to be always run from workqueue - which acts as
* read-size critical section for our kind of RCU. */
static void handle_rx(struct vhost_net *net)
{
struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
- unsigned head, out, in, log, s;
+ unsigned in, log, s;
struct vhost_log *vq_log;
struct msghdr msg = {
.msg_name = NULL,
@@ -204,10 +213,11 @@
};
size_t len, total_len = 0;
- int err;
+ int err, headcount, datalen;
size_t hdr_size;
struct socket *sock = rcu_dereference(vq->private_data);
- if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
+
+ if (!sock || !skb_head_len(&sock->sk->sk_receive_queue))
return;
use_mm(net->dev.mm);
@@ -218,13 +228,10 @@
vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
vq->log : NULL;
- for (;;) {
- head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
- ARRAY_SIZE(vq->iov),
- &out, &in,
- vq_log, &log);
+ while ((datalen = skb_head_len(&sock->sk->sk_receive_queue))) {
+ headcount = vhost_get_heads(vq, datalen, &in, vq_log, &log);
/* OK, now we need to know about added descriptors. */
- if (head == vq->num) {
+ if (!headcount) {
if (unlikely(vhost_enable_notify(vq))) {
/* They have slipped one in as we were
* doing that: check again. */
@@ -235,13 +242,6 @@
* they refilled. */
break;
}
- /* We don't need to be notified again. */
- if (out) {
- vq_err(vq, "Unexpected descriptor format for RX: "
- "out %d, int %d\n",
- out, in);
- break;
- }
/* Skip header. TODO: support TSO/mergeable rx buffers. */
s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in);
msg.msg_iovlen = in;
@@ -257,14 +257,14 @@
len, MSG_DONTWAIT | MSG_TRUNC);
/* TODO: Check specific error and bomb out unless EAGAIN? */
if (err < 0) {
- vhost_discard_vq_desc(vq);
+ vhost_discard(vq, 1);
break;
}
/* TODO: Should check and handle checksum. */
if (err > len) {
pr_err("Discarded truncated rx packet: "
" len %d > %zd\n", err, len);
- vhost_discard_vq_desc(vq);
+ vhost_discard(vq, 1);
continue;
}
len = err;
@@ -275,7 +275,7 @@
break;
}
len += hdr_size;
- vhost_add_used_and_signal(&net->dev, vq, head, len);
+ vhost_add_used_and_signal(&net->dev, vq, vq->heads, headcount);
if (unlikely(vq_log))
vhost_log_write(vq, vq_log, log, len);
total_len += len;
diff -ruN net-next-p0/drivers/vhost/vhost.c net-next-p1/drivers/vhost/vhost.c
--- net-next-p0/drivers/vhost/vhost.c 2010-02-15 20:08:35.000000000 -0800
+++ net-next-p1/drivers/vhost/vhost.c 2010-03-01 11:44:06.000000000 -0800
@@ -848,6 +848,38 @@
return 0;
}
+unsigned vhost_get_heads(struct vhost_virtqueue *vq, int datalen, int *iovcount,
+ struct vhost_log *log, unsigned int *log_num)
+{
+ struct iovec *heads = vq->heads;
+ int out, in;
+ int hc = 0;
+
+ while (datalen > 0) {
+ if (hc >= VHOST_NET_MAX_SG) {
+ vhost_discard(vq, hc);
+ return 0;
+ }
+ heads[hc].iov_base = (void *)vhost_get_vq_desc(vq->dev, vq,
+ vq->iov, ARRAY_SIZE(vq->iov), &out, &in, log, log_num);
+ if (heads[hc].iov_base == (void *)vq->num) {
+ vhost_discard(vq, hc);
+ return 0;
+ }
+ if (out || in <= 0) {
+ vq_err(vq, "unexpected descriptor format for RX: "
+ "out %d, in %d\n", out, in);
+ vhost_discard(vq, hc);
+ return 0;
+ }
+ heads[hc].iov_len = iov_length(vq->iov, in);
+ hc++;
+ datalen -= heads[hc].iov_len;
+ }
+ *iovcount = in;
+ return hc;
+}
+
/* This looks in the virtqueue and for the first available buffer, and converts
* it to an iovec for convenient access. Since descriptors consist of some
* number of output then some number of input descriptors, it's actually two
@@ -973,31 +1005,32 @@
}
/* Reverse the effect of vhost_get_vq_desc. Useful for error handling. */
-void vhost_discard_vq_desc(struct vhost_virtqueue *vq)
+void vhost_discard(struct vhost_virtqueue *vq, int n)
{
- vq->last_avail_idx--;
+ vq->last_avail_idx -= n;
}
/* After we've used one of their buffers, we tell them about it. We'll then
* want to notify the guest, using eventfd. */
-int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len)
+int vhost_add_used(struct vhost_virtqueue *vq, struct iovec *heads, int count)
{
struct vring_used_elem *used;
+ int i;
- /* The virtqueue contains a ring of used buffers. Get a pointer to the
- * next entry in that used ring. */
- used = &vq->used->ring[vq->last_used_idx % vq->num];
- if (put_user(head, &used->id)) {
- vq_err(vq, "Failed to write used id");
- return -EFAULT;
- }
- if (put_user(len, &used->len)) {
- vq_err(vq, "Failed to write used len");
- return -EFAULT;
+ for (i=0; i<count; i++, vq->last_used_idx++) {
+ used = &vq->used->ring[vq->last_used_idx % vq->num];
+ if (put_user((unsigned)heads[i].iov_base, &used->id)) {
+ vq_err(vq, "Failed to write used id");
+ return -EFAULT;
+ }
+ if (put_user(heads[i].iov_len, &used->len)) {
+ vq_err(vq, "Failed to write used len");
+ return -EFAULT;
+ }
}
/* Make sure buffer is written before we update index. */
smp_wmb();
- if (put_user(vq->last_used_idx + 1, &vq->used->idx)) {
+ if (put_user(vq->last_used_idx, &vq->used->idx)) {
vq_err(vq, "Failed to increment used idx");
return -EFAULT;
}
@@ -1011,7 +1044,6 @@
if (vq->log_ctx)
eventfd_signal(vq->log_ctx, 1);
}
- vq->last_used_idx++;
return 0;
}
@@ -1038,9 +1070,9 @@
/* And here's the combo meal deal. Supersize me! */
void vhost_add_used_and_signal(struct vhost_dev *dev,
struct vhost_virtqueue *vq,
- unsigned int head, int len)
+ struct iovec *heads, int count)
{
- vhost_add_used(vq, head, len);
+ vhost_add_used(vq, heads, count);
vhost_signal(dev, vq);
}
diff -ruN net-next-p0/drivers/vhost/vhost.h net-next-p1/drivers/vhost/vhost.h
--- net-next-p0/drivers/vhost/vhost.h 2010-02-15 20:08:35.000000000 -0800
+++ net-next-p1/drivers/vhost/vhost.h 2010-03-01 11:42:18.000000000 -0800
@@ -84,6 +84,7 @@
struct iovec indirect[VHOST_NET_MAX_SG];
struct iovec iov[VHOST_NET_MAX_SG];
struct iovec hdr[VHOST_NET_MAX_SG];
+ struct iovec heads[VHOST_NET_MAX_SG];
size_t hdr_size;
/* We use a kind of RCU to access private pointer.
* All readers access it from workqueue, which makes it possible to
@@ -120,16 +121,18 @@
int vhost_vq_access_ok(struct vhost_virtqueue *vq);
int vhost_log_access_ok(struct vhost_dev *);
+unsigned vhost_get_heads(struct vhost_virtqueue *, int datalen, int *iovcount,
+ struct vhost_log *log, unsigned int *log_num);
unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
struct iovec iov[], unsigned int iov_count,
unsigned int *out_num, unsigned int *in_num,
struct vhost_log *log, unsigned int *log_num);
-void vhost_discard_vq_desc(struct vhost_virtqueue *);
+void vhost_discard(struct vhost_virtqueue *, int);
-int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
-void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
+int vhost_add_used(struct vhost_virtqueue *, struct iovec *heads, int count);
void vhost_add_used_and_signal(struct vhost_dev *, struct vhost_virtqueue *,
- unsigned int head, int len);
+ struct iovec *heads, int count);
+void vhost_signal(struct vhost_dev *, struct vhost_virtqueue *);
void vhost_disable_notify(struct vhost_virtqueue *);
bool vhost_enable_notify(struct vhost_virtqueue *);
^ permalink raw reply
* [RFC][ PATCH 2/3] vhost-net: handle vnet_hdr processing for MRG_RX_BUF
From: David Stevens @ 2010-03-03 0:20 UTC (permalink / raw)
To: mst, rusty; +Cc: netdev, kvm, virtualization
[-- Attachment #1: Type: text/plain, Size: 13122 bytes --]
This patch adds vnet_hdr processing for mergeable buffer
support to vhost-net.
Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
diff -ruN net-next-p1/drivers/vhost/net.c net-next-p2/drivers/vhost/net.c
--- net-next-p1/drivers/vhost/net.c 2010-03-01 11:44:22.000000000
-0800
+++ net-next-p2/drivers/vhost/net.c 2010-03-02 13:01:34.000000000
-0800
@@ -109,7 +109,6 @@
};
size_t len, total_len = 0;
int err, wmem;
- size_t hdr_size;
struct socket *sock = rcu_dereference(vq->private_data);
if (!sock)
return;
@@ -124,7 +123,6 @@
if (wmem < sock->sk->sk_sndbuf * 2)
tx_poll_stop(net);
- hdr_size = vq->hdr_size;
for (;;) {
head.iov_base = (void *)vhost_get_vq_desc(&net->dev, vq,
@@ -148,25 +146,45 @@
"out %d, int %d\n", out, in);
break;
}
+ if (vq->guest_hlen > vq->sock_hlen) {
+ if (msg.msg_iov[0].iov_len == vq->guest_hlen)
+ msg.msg_iov[0].iov_len = vq->sock_hlen;
+ else if (out == ARRAY_SIZE(vq->iov))
+ vq_err(vq, "handle_tx iov overflow!");
+ else {
+ int i;
+
+ /* give header its own iov */
+ for (i=out; i>0; ++i)
+ msg.msg_iov[i+1] = msg.msg_iov[i];
+ msg.msg_iov[0].iov_len = vq->sock_hlen;
+ msg.msg_iov[1].iov_base += vq->guest_hlen;
+ msg.msg_iov[1].iov_len -= vq->guest_hlen;
+ out++;
+ }
+ }
/* Skip header. TODO: support TSO. */
- s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, out);
msg.msg_iovlen = out;
head.iov_len = len = iov_length(vq->iov, out);
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for TX: "
"%zd expected %zd\n",
- iov_length(vq->hdr, s), hdr_size);
+ len, vq->guest_hlen);
break;
}
/* TODO: Check specific error and bomb out unless ENOBUFS?
*/
err = sock->ops->sendmsg(NULL, sock, &msg, len);
if (unlikely(err < 0)) {
- vhost_discard(vq, 1);
- tx_poll_start(net, sock);
+ if (err == -EAGAIN) {
+ tx_poll_start(net, sock);
+ } else {
+ vq_err(vq, "sendmsg: errno %d\n", -err);
+ /* drop packet; do not discard/resend */
+ vhost_add_used_and_signal(&net->dev,vq,&head,1);
+ }
break;
- }
- if (err != len)
+ } else if (err != len)
pr_err("Truncated TX packet: "
" len %d != %zd\n", err, len);
vhost_add_used_and_signal(&net->dev, vq, &head, 1);
@@ -207,14 +225,8 @@
.msg_flags = MSG_DONTWAIT,
};
- struct virtio_net_hdr hdr = {
- .flags = 0,
- .gso_type = VIRTIO_NET_HDR_GSO_NONE
- };
-
size_t len, total_len = 0;
int err, headcount, datalen;
- size_t hdr_size;
struct socket *sock = rcu_dereference(vq->private_data);
if (!sock || !skb_head_len(&sock->sk->sk_receive_queue))
@@ -223,7 +235,6 @@
use_mm(net->dev.mm);
mutex_lock(&vq->mutex);
vhost_disable_notify(vq);
- hdr_size = vq->hdr_size;
vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
vq->log : NULL;
@@ -232,25 +243,18 @@
headcount = vhost_get_heads(vq, datalen, &in, vq_log,
&log);
/* OK, now we need to know about added descriptors. */
if (!headcount) {
- if (unlikely(vhost_enable_notify(vq))) {
- /* They have slipped one in as we were
- * doing that: check again. */
- vhost_disable_notify(vq);
- continue;
- }
- /* Nothing new? Wait for eventfd to tell us
- * they refilled. */
+ vhost_enable_notify(vq);
break;
}
/* Skip header. TODO: support TSO/mergeable rx buffers. */
- s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in);
msg.msg_iovlen = in;
len = iov_length(vq->iov, in);
+
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for RX: "
"%zd expected %zd\n",
- iov_length(vq->hdr, s), hdr_size);
+ len, vq->guest_hlen);
break;
}
err = sock->ops->recvmsg(NULL, sock, &msg,
@@ -268,13 +272,7 @@
continue;
}
len = err;
- err = memcpy_toiovec(vq->hdr, (unsigned char *)&hdr,
hdr_size);
- if (err) {
- vq_err(vq, "Unable to write vnet_hdr at addr %p:
%d\n",
- vq->iov->iov_base, err);
- break;
- }
- len += hdr_size;
+ len += vq->guest_hlen - vq->sock_hlen;
vhost_add_used_and_signal(&net->dev, vq, vq->heads,
headcount);
if (unlikely(vq_log))
vhost_log_write(vq, vq_log, log, len);
@@ -483,6 +481,13 @@
return ERR_PTR(-ENOTSOCK);
}
+static int vhost_sock_is_raw(struct socket *sock)
+{
+ if (!sock || !sock->sk)
+ return 0;
+ return sock->sk->sk_type == SOCK_RAW;
+}
+
static long vhost_net_set_backend(struct vhost_net *n, unsigned index,
int fd)
{
struct socket *sock, *oldsock;
@@ -519,6 +524,20 @@
vhost_net_disable_vq(n, vq);
rcu_assign_pointer(vq->private_data, sock);
+
+ if (sock && sock->sk) {
+ if (!vhost_sock_is_raw(sock) ||
+ vhost_has_feature(&n->dev,
VHOST_NET_F_VIRTIO_NET_HDR)) {
+ vq->sock_hlen = sizeof(struct virtio_net_hdr);
+ if (vhost_has_feature(&n->dev,
VIRTIO_NET_F_MRG_RXBUF))
+ vq->guest_hlen =
+ sizeof(struct
virtio_net_hdr_mrg_rxbuf);
+ else
+ vq->guest_hlen = sizeof(struct
virtio_net_hdr);
+ } else
+ vq->guest_hlen = vq->sock_hlen = 0;
+ } else
+ vq_err(vq, "vhost_net_set_backend: sock->sk is NULL");
vhost_net_enable_vq(n, vq);
mutex_unlock(&vq->mutex);
done:
@@ -566,8 +585,17 @@
n->dev.acked_features = features;
smp_wmb();
for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
- mutex_lock(&n->vqs[i].mutex);
- n->vqs[i].hdr_size = hdr_size;
+ struct vhost_virtqueue *vq = n->vqs + i;
+ struct socket *sock = vq->private_data;
+
+ mutex_lock(&vq->mutex);
+ if (features & (1 << VIRTIO_NET_F_MRG_RXBUF))
+ vq->sock_hlen = sizeof(struct
virtio_net_hdr_mrg_rxbuf);
+ else if (features & (1 << VHOST_NET_F_VIRTIO_NET_HDR) ||
+ !vhost_sock_is_raw(sock))
+ vq->sock_hlen = sizeof(struct virtio_net_hdr);
+ else
+ vq->sock_hlen = 0;
mutex_unlock(&n->vqs[i].mutex);
}
vhost_net_flush(n);
diff -ruN net-next-p1/drivers/vhost/vhost.c
net-next-p2/drivers/vhost/vhost.c
--- net-next-p1/drivers/vhost/vhost.c 2010-03-01 11:44:06.000000000
-0800
+++ net-next-p2/drivers/vhost/vhost.c 2010-03-02 12:53:02.000000000
-0800
@@ -113,7 +113,8 @@
vq->used_flags = 0;
vq->log_used = false;
vq->log_addr = -1ull;
- vq->hdr_size = 0;
+ vq->guest_hlen = 0;
+ vq->sock_hlen = 0;
vq->private_data = NULL;
vq->log_base = NULL;
vq->error_ctx = NULL;
@@ -848,20 +849,85 @@
return 0;
}
+static int
+vhost_get_hdr(struct vhost_virtqueue *vq, int *in, struct vhost_log *log,
+ int *log_num)
+{
+ struct iovec *heads = vq->heads;
+ struct iovec *iov = vq->iov;
+ int out;
+
+ *in = 0;
+ iov[0].iov_len = 0;
+
+ /* get buffer, starting from iov[1] */
+ heads[0].iov_base = (void *)vhost_get_vq_desc(vq->dev, vq,
+ vq->iov+1, ARRAY_SIZE(vq->iov)-1, &out, in, log, log_num);
+ if (out || *in <= 0) {
+ vq_err(vq, "unexpected descriptor format for RX: out %d, "
+ "in %d\n", out, *in);
+ return 0;
+ }
+ if (heads[0].iov_base == (void *)vq->num)
+ return 0;
+
+ /* make iov[0] the header */
+ if (!vq->guest_hlen) {
+ if (vq->sock_hlen) {
+ static struct virtio_net_hdr junk; /* bit bucket
*/
+
+ iov[0].iov_base = &junk;
+ iov[0].iov_len = sizeof(junk);
+ } else
+ iov[0].iov_len = 0;
+ }
+ if (vq->sock_hlen < vq->guest_hlen) {
+ iov[0].iov_base = iov[1].iov_base;
+ iov[0].iov_len = vq->sock_hlen;
+
+ if (iov[1].iov_len < vq->sock_hlen) {
+ vq_err(vq, "can't fit header in one buffer!");
+ vhost_discard(vq, 1);
+ return 0;
+ }
+ if (!vq->sock_hlen) {
+ static const struct virtio_net_hdr_mrg_rxbuf hdr =
{
+ .hdr.flags = 0,
+ .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
+ };
+ memcpy(iov[0].iov_base, &hdr, vq->guest_hlen);
+ }
+ iov[1].iov_base += vq->guest_hlen;
+ iov[1].iov_len -= vq->guest_hlen;
+ }
+ return 1;
+}
+
unsigned vhost_get_heads(struct vhost_virtqueue *vq, int datalen, int
*iovcount,
struct vhost_log *log, unsigned int *log_num)
{
struct iovec *heads = vq->heads;
- int out, in;
+ int out, in = 0;
+ int seg = 0;
int hc = 0;
+ if (vq->guest_hlen != vq->sock_hlen) {
+ seg = vhost_get_hdr(vq, &in, log, log_num);
+ if (!seg)
+ return 0;
+ hc++;
+ datalen -= iov_length(vq->iov+seg, in);
+ seg += in;
+ }
+
while (datalen > 0) {
if (hc >= VHOST_NET_MAX_SG) {
vhost_discard(vq, hc);
return 0;
}
heads[hc].iov_base = (void *)vhost_get_vq_desc(vq->dev,
vq,
- vq->iov, ARRAY_SIZE(vq->iov), &out, &in, log,
log_num);
+ vq->iov+seg, ARRAY_SIZE(vq->iov)-seg, &out, &in,
+ log, log_num);
if (heads[hc].iov_base == (void *)vq->num) {
vhost_discard(vq, hc);
return 0;
@@ -872,11 +938,12 @@
vhost_discard(vq, hc);
return 0;
}
- heads[hc].iov_len = iov_length(vq->iov, in);
- hc++;
+ heads[hc].iov_len = iov_length(vq->iov+seg, in);
datalen -= heads[hc].iov_len;
+ hc++;
+ seg += in;
}
- *iovcount = in;
+ *iovcount = seg;
return hc;
}
diff -ruN net-next-p1/drivers/vhost/vhost.h
net-next-p2/drivers/vhost/vhost.h
--- net-next-p1/drivers/vhost/vhost.h 2010-03-01 11:42:18.000000000
-0800
+++ net-next-p2/drivers/vhost/vhost.h 2010-03-02 13:02:03.000000000
-0800
@@ -82,10 +82,9 @@
u64 log_addr;
struct iovec indirect[VHOST_NET_MAX_SG];
- struct iovec iov[VHOST_NET_MAX_SG];
- struct iovec hdr[VHOST_NET_MAX_SG];
+ struct iovec iov[VHOST_NET_MAX_SG+1]; /* an extra for vnet hdr */
struct iovec heads[VHOST_NET_MAX_SG];
- size_t hdr_size;
+ size_t guest_hlen, sock_hlen;
/* We use a kind of RCU to access private pointer.
* All readers access it from workqueue, which makes it possible
to
* flush the workqueue instead of synchronize_rcu. Therefore
readers do
[-- Attachment #2: MRXB2.patch --]
[-- Type: application/octet-stream, Size: 9374 bytes --]
diff -ruN net-next-p1/drivers/vhost/net.c net-next-p2/drivers/vhost/net.c
--- net-next-p1/drivers/vhost/net.c 2010-03-01 11:44:22.000000000 -0800
+++ net-next-p2/drivers/vhost/net.c 2010-03-02 13:01:34.000000000 -0800
@@ -109,7 +109,6 @@
};
size_t len, total_len = 0;
int err, wmem;
- size_t hdr_size;
struct socket *sock = rcu_dereference(vq->private_data);
if (!sock)
return;
@@ -124,7 +123,6 @@
if (wmem < sock->sk->sk_sndbuf * 2)
tx_poll_stop(net);
- hdr_size = vq->hdr_size;
for (;;) {
head.iov_base = (void *)vhost_get_vq_desc(&net->dev, vq,
@@ -148,25 +146,45 @@
"out %d, int %d\n", out, in);
break;
}
+ if (vq->guest_hlen > vq->sock_hlen) {
+ if (msg.msg_iov[0].iov_len == vq->guest_hlen)
+ msg.msg_iov[0].iov_len = vq->sock_hlen;
+ else if (out == ARRAY_SIZE(vq->iov))
+ vq_err(vq, "handle_tx iov overflow!");
+ else {
+ int i;
+
+ /* give header its own iov */
+ for (i=out; i>0; ++i)
+ msg.msg_iov[i+1] = msg.msg_iov[i];
+ msg.msg_iov[0].iov_len = vq->sock_hlen;
+ msg.msg_iov[1].iov_base += vq->guest_hlen;
+ msg.msg_iov[1].iov_len -= vq->guest_hlen;
+ out++;
+ }
+ }
/* Skip header. TODO: support TSO. */
- s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, out);
msg.msg_iovlen = out;
head.iov_len = len = iov_length(vq->iov, out);
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for TX: "
"%zd expected %zd\n",
- iov_length(vq->hdr, s), hdr_size);
+ len, vq->guest_hlen);
break;
}
/* TODO: Check specific error and bomb out unless ENOBUFS? */
err = sock->ops->sendmsg(NULL, sock, &msg, len);
if (unlikely(err < 0)) {
- vhost_discard(vq, 1);
- tx_poll_start(net, sock);
+ if (err == -EAGAIN) {
+ tx_poll_start(net, sock);
+ } else {
+ vq_err(vq, "sendmsg: errno %d\n", -err);
+ /* drop packet; do not discard/resend */
+ vhost_add_used_and_signal(&net->dev,vq,&head,1);
+ }
break;
- }
- if (err != len)
+ } else if (err != len)
pr_err("Truncated TX packet: "
" len %d != %zd\n", err, len);
vhost_add_used_and_signal(&net->dev, vq, &head, 1);
@@ -207,14 +225,8 @@
.msg_flags = MSG_DONTWAIT,
};
- struct virtio_net_hdr hdr = {
- .flags = 0,
- .gso_type = VIRTIO_NET_HDR_GSO_NONE
- };
-
size_t len, total_len = 0;
int err, headcount, datalen;
- size_t hdr_size;
struct socket *sock = rcu_dereference(vq->private_data);
if (!sock || !skb_head_len(&sock->sk->sk_receive_queue))
@@ -223,7 +235,6 @@
use_mm(net->dev.mm);
mutex_lock(&vq->mutex);
vhost_disable_notify(vq);
- hdr_size = vq->hdr_size;
vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
vq->log : NULL;
@@ -232,25 +243,18 @@
headcount = vhost_get_heads(vq, datalen, &in, vq_log, &log);
/* OK, now we need to know about added descriptors. */
if (!headcount) {
- if (unlikely(vhost_enable_notify(vq))) {
- /* They have slipped one in as we were
- * doing that: check again. */
- vhost_disable_notify(vq);
- continue;
- }
- /* Nothing new? Wait for eventfd to tell us
- * they refilled. */
+ vhost_enable_notify(vq);
break;
}
/* Skip header. TODO: support TSO/mergeable rx buffers. */
- s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in);
msg.msg_iovlen = in;
len = iov_length(vq->iov, in);
+
/* Sanity check */
if (!len) {
vq_err(vq, "Unexpected header len for RX: "
"%zd expected %zd\n",
- iov_length(vq->hdr, s), hdr_size);
+ len, vq->guest_hlen);
break;
}
err = sock->ops->recvmsg(NULL, sock, &msg,
@@ -268,13 +272,7 @@
continue;
}
len = err;
- err = memcpy_toiovec(vq->hdr, (unsigned char *)&hdr, hdr_size);
- if (err) {
- vq_err(vq, "Unable to write vnet_hdr at addr %p: %d\n",
- vq->iov->iov_base, err);
- break;
- }
- len += hdr_size;
+ len += vq->guest_hlen - vq->sock_hlen;
vhost_add_used_and_signal(&net->dev, vq, vq->heads, headcount);
if (unlikely(vq_log))
vhost_log_write(vq, vq_log, log, len);
@@ -483,6 +481,13 @@
return ERR_PTR(-ENOTSOCK);
}
+static int vhost_sock_is_raw(struct socket *sock)
+{
+ if (!sock || !sock->sk)
+ return 0;
+ return sock->sk->sk_type == SOCK_RAW;
+}
+
static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
{
struct socket *sock, *oldsock;
@@ -519,6 +524,20 @@
vhost_net_disable_vq(n, vq);
rcu_assign_pointer(vq->private_data, sock);
+
+ if (sock && sock->sk) {
+ if (!vhost_sock_is_raw(sock) ||
+ vhost_has_feature(&n->dev, VHOST_NET_F_VIRTIO_NET_HDR)) {
+ vq->sock_hlen = sizeof(struct virtio_net_hdr);
+ if (vhost_has_feature(&n->dev, VIRTIO_NET_F_MRG_RXBUF))
+ vq->guest_hlen =
+ sizeof(struct virtio_net_hdr_mrg_rxbuf);
+ else
+ vq->guest_hlen = sizeof(struct virtio_net_hdr);
+ } else
+ vq->guest_hlen = vq->sock_hlen = 0;
+ } else
+ vq_err(vq, "vhost_net_set_backend: sock->sk is NULL");
vhost_net_enable_vq(n, vq);
mutex_unlock(&vq->mutex);
done:
@@ -566,8 +585,17 @@
n->dev.acked_features = features;
smp_wmb();
for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
- mutex_lock(&n->vqs[i].mutex);
- n->vqs[i].hdr_size = hdr_size;
+ struct vhost_virtqueue *vq = n->vqs + i;
+ struct socket *sock = vq->private_data;
+
+ mutex_lock(&vq->mutex);
+ if (features & (1 << VIRTIO_NET_F_MRG_RXBUF))
+ vq->sock_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);
+ else if (features & (1 << VHOST_NET_F_VIRTIO_NET_HDR) ||
+ !vhost_sock_is_raw(sock))
+ vq->sock_hlen = sizeof(struct virtio_net_hdr);
+ else
+ vq->sock_hlen = 0;
mutex_unlock(&n->vqs[i].mutex);
}
vhost_net_flush(n);
diff -ruN net-next-p1/drivers/vhost/vhost.c net-next-p2/drivers/vhost/vhost.c
--- net-next-p1/drivers/vhost/vhost.c 2010-03-01 11:44:06.000000000 -0800
+++ net-next-p2/drivers/vhost/vhost.c 2010-03-02 12:53:02.000000000 -0800
@@ -113,7 +113,8 @@
vq->used_flags = 0;
vq->log_used = false;
vq->log_addr = -1ull;
- vq->hdr_size = 0;
+ vq->guest_hlen = 0;
+ vq->sock_hlen = 0;
vq->private_data = NULL;
vq->log_base = NULL;
vq->error_ctx = NULL;
@@ -848,20 +849,85 @@
return 0;
}
+static int
+vhost_get_hdr(struct vhost_virtqueue *vq, int *in, struct vhost_log *log,
+ int *log_num)
+{
+ struct iovec *heads = vq->heads;
+ struct iovec *iov = vq->iov;
+ int out;
+
+ *in = 0;
+ iov[0].iov_len = 0;
+
+ /* get buffer, starting from iov[1] */
+ heads[0].iov_base = (void *)vhost_get_vq_desc(vq->dev, vq,
+ vq->iov+1, ARRAY_SIZE(vq->iov)-1, &out, in, log, log_num);
+ if (out || *in <= 0) {
+ vq_err(vq, "unexpected descriptor format for RX: out %d, "
+ "in %d\n", out, *in);
+ return 0;
+ }
+ if (heads[0].iov_base == (void *)vq->num)
+ return 0;
+
+ /* make iov[0] the header */
+ if (!vq->guest_hlen) {
+ if (vq->sock_hlen) {
+ static struct virtio_net_hdr junk; /* bit bucket */
+
+ iov[0].iov_base = &junk;
+ iov[0].iov_len = sizeof(junk);
+ } else
+ iov[0].iov_len = 0;
+ }
+ if (vq->sock_hlen < vq->guest_hlen) {
+ iov[0].iov_base = iov[1].iov_base;
+ iov[0].iov_len = vq->sock_hlen;
+
+ if (iov[1].iov_len < vq->sock_hlen) {
+ vq_err(vq, "can't fit header in one buffer!");
+ vhost_discard(vq, 1);
+ return 0;
+ }
+ if (!vq->sock_hlen) {
+ static const struct virtio_net_hdr_mrg_rxbuf hdr = {
+ .hdr.flags = 0,
+ .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
+ };
+ memcpy(iov[0].iov_base, &hdr, vq->guest_hlen);
+ }
+ iov[1].iov_base += vq->guest_hlen;
+ iov[1].iov_len -= vq->guest_hlen;
+ }
+ return 1;
+}
+
unsigned vhost_get_heads(struct vhost_virtqueue *vq, int datalen, int *iovcount,
struct vhost_log *log, unsigned int *log_num)
{
struct iovec *heads = vq->heads;
- int out, in;
+ int out, in = 0;
+ int seg = 0;
int hc = 0;
+ if (vq->guest_hlen != vq->sock_hlen) {
+ seg = vhost_get_hdr(vq, &in, log, log_num);
+ if (!seg)
+ return 0;
+ hc++;
+ datalen -= iov_length(vq->iov+seg, in);
+ seg += in;
+ }
+
while (datalen > 0) {
if (hc >= VHOST_NET_MAX_SG) {
vhost_discard(vq, hc);
return 0;
}
heads[hc].iov_base = (void *)vhost_get_vq_desc(vq->dev, vq,
- vq->iov, ARRAY_SIZE(vq->iov), &out, &in, log, log_num);
+ vq->iov+seg, ARRAY_SIZE(vq->iov)-seg, &out, &in,
+ log, log_num);
if (heads[hc].iov_base == (void *)vq->num) {
vhost_discard(vq, hc);
return 0;
@@ -872,11 +938,12 @@
vhost_discard(vq, hc);
return 0;
}
- heads[hc].iov_len = iov_length(vq->iov, in);
- hc++;
+ heads[hc].iov_len = iov_length(vq->iov+seg, in);
datalen -= heads[hc].iov_len;
+ hc++;
+ seg += in;
}
- *iovcount = in;
+ *iovcount = seg;
return hc;
}
diff -ruN net-next-p1/drivers/vhost/vhost.h net-next-p2/drivers/vhost/vhost.h
--- net-next-p1/drivers/vhost/vhost.h 2010-03-01 11:42:18.000000000 -0800
+++ net-next-p2/drivers/vhost/vhost.h 2010-03-02 13:02:03.000000000 -0800
@@ -82,10 +82,9 @@
u64 log_addr;
struct iovec indirect[VHOST_NET_MAX_SG];
- struct iovec iov[VHOST_NET_MAX_SG];
- struct iovec hdr[VHOST_NET_MAX_SG];
+ struct iovec iov[VHOST_NET_MAX_SG+1]; /* an extra for vnet hdr */
struct iovec heads[VHOST_NET_MAX_SG];
- size_t hdr_size;
+ size_t guest_hlen, sock_hlen;
/* We use a kind of RCU to access private pointer.
* All readers access it from workqueue, which makes it possible to
* flush the workqueue instead of synchronize_rcu. Therefore readers do
^ permalink raw reply
* [RFC][ PATCH 0/3] vhost-net: Add mergeable RX buffer support to vhost-net
From: David Stevens @ 2010-03-03 0:20 UTC (permalink / raw)
To: mst, rusty; +Cc: netdev, kvm, virtualization
These patches add support for mergeable receive buffers to
vhost-net, allowing it to use multiple virtio buffer heads for a single
receive packet.
+-DLS
Signed-off-by: David L Stevens <dlstevens@us.ibm.com>
^ permalink raw reply
* Re: [RFC][PATCH] ns: Syscalls for better namespace sharing control.
From: Sukadev Bhattiprolu @ 2010-03-03 0:07 UTC (permalink / raw)
To: Eric W. Biederman
Cc: Pavel Emelyanov, Daniel Lezcano, Linux Netdev List, containers,
Netfilter Development Mailinglist, Ben Greear
In-Reply-To: <m1y6iaqsmm.fsf@fess.ebiederm.org>
Eric W. Biederman [ebiederm@xmission.com] wrote:
|
| I think replacing a struct pid for another struct pid allocated in
| descendant pid_namespace (but has all of the same struct upid values
| as the first struct pid) is a disastrous idea. It destroys the
True. Sorry, I did not mean we would need a new 'struct pid' for an
existing process. I think we talked earlier of finding a way of attaching
additional pid numbers to the same struct pid.
Sukadev
^ permalink raw reply
* Re: [RFC v2 03/10] snet: introduce security/snet, Makefile and Kconfig changes
From: Greg KH @ 2010-03-03 0:03 UTC (permalink / raw)
To: Samir Bellabes
Cc: linux-security-module, linux-kernel, netdev, netfilter-devel,
jamal, Patrick McHardy, Evgeniy Polyakov, Neil Horman,
Grzegorz Nosek
In-Reply-To: <1267561394-13626-4-git-send-email-sam@synack.fr>
On Tue, Mar 02, 2010 at 09:23:07PM +0100, Samir Bellabes wrote:
> this patch creates folder security/snet and adds changes for Kconfig and Makefile
But it breaks the build, as you are referring to files here that are not
present yet. Please put this at the end of your patch series to make
the tree always build for every individual patch.
thanks,
greg k-h
^ 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