Netdev List
 help / color / mirror / Atom feed
* Re: [PATCHv6 1/3] tun: export underlying socket
From: Arnd Bergmann @ 2009-11-03 12:12 UTC (permalink / raw)
  To: virtualization
  Cc: Michael S. Tsirkin, netdev, kvm, linux-kernel, mingo, linux-mm,
	akpm, hpa, gregory.haskins, Rusty Russell, s.hetze
In-Reply-To: <20091102222612.GB15184@redhat.com>

On Monday 02 November 2009, Michael S. Tsirkin wrote:
> Tun device looks similar to a packet socket
> in that both pass complete frames from/to userspace.
> 
> This patch fills in enough fields in the socket underlying tun driver
> to support sendmsg/recvmsg operations, and message flags
> MSG_TRUNC and MSG_DONTWAIT, and exports access to this socket
> to modules.  Regular read/write behaviour is unchanged.
> 
> This way, code using raw sockets to inject packets
> into a physical device, can support injecting
> packets into host network stack almost without modification.
> 
> First user of this interface will be vhost virtualization
> accelerator.

You mentioned before that you wanted to export the socket
using some ioctl function returning an open file descriptor,
which seemed to be a cleaner approach than this one.

What was your reason for changing?

> index 3f5fd52..404abe0 100644
> --- a/include/linux/if_tun.h
> +++ b/include/linux/if_tun.h
> @@ -86,4 +86,18 @@ struct tun_filter {
>         __u8   addr[0][ETH_ALEN];
>  };
>  
> +#ifdef __KERNEL__
> +#if defined(CONFIG_TUN) || defined(CONFIG_TUN_MODULE)
> +struct socket *tun_get_socket(struct file *);
> +#else
> +#include <linux/err.h>
> +#include <linux/errno.h>
> +struct file;
> +struct socket;
> +static inline struct socket *tun_get_socket(struct file *f)
> +{
> +       return ERR_PTR(-EINVAL);
> +}
> +#endif /* CONFIG_TUN */
> +#endif /* __KERNEL__ */
>  #endif /* __IF_TUN_H */

Is this a leftover from testing? Exporting the function for !__KERNEL__
seems pointless.

	Arnd <><

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCHv6 1/3] tun: export underlying socket
From: Michael S. Tsirkin @ 2009-11-03 12:31 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: virtualization, netdev, kvm, linux-kernel, mingo, linux-mm, akpm,
	hpa, gregory.haskins, Rusty Russell, s.hetze
In-Reply-To: <200911031312.33580.arnd@arndb.de>

On Tue, Nov 03, 2009 at 01:12:33PM +0100, Arnd Bergmann wrote:
> On Monday 02 November 2009, Michael S. Tsirkin wrote:
> > Tun device looks similar to a packet socket
> > in that both pass complete frames from/to userspace.
> > 
> > This patch fills in enough fields in the socket underlying tun driver
> > to support sendmsg/recvmsg operations, and message flags
> > MSG_TRUNC and MSG_DONTWAIT, and exports access to this socket
> > to modules.  Regular read/write behaviour is unchanged.
> > 
> > This way, code using raw sockets to inject packets
> > into a physical device, can support injecting
> > packets into host network stack almost without modification.
> > 
> > First user of this interface will be vhost virtualization
> > accelerator.
> 
> You mentioned before that you wanted to export the socket
> using some ioctl function returning an open file descriptor,
> which seemed to be a cleaner approach than this one.

Note that a similar feature can be implemented on top of tun_get_socket,
as seen from patch below.

> What was your reason for changing?

It turns out socket structure is really bound to specific a file, so we
can not have 2 files referencing the same socket.  Instead, as I say
above, it's possible to make sendmsg/recvmsg work on tap file directly.

For vhost, the advantage of such a feature over using tun_get_socket
directly would be that vhost module won't depend on tun module then.  I
have implemented this (patch below), but decided to go with the simple
thing first.  Since no userspace-visible changes are involved, let's do
this by small steps: it will be easier to figure out when vhost
is upstream.


---

Note: patch below aplies on top of patch tun: export underlying socket.
It is not intended for merge yet.

net: convert tun device to socket

Add callback to file_ops to retrieve socket from
file structure. Use this to make tun character device
accept sendmsg/recvmsg calls.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index b58095a..53e1806 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1405,7 +1405,8 @@ static const struct file_operations tun_fops = {
 	.unlocked_ioctl = tun_chr_ioctl,
 	.open	= tun_chr_open,
 	.release = tun_chr_close,
-	.fasync = tun_chr_fasync
+	.fasync = tun_chr_fasync,
+	.get_socket = tun_get_socket,
 };
 
 static struct miscdevice tun_miscdev = {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2620a8c..f2b381f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1506,6 +1506,9 @@ struct file_operations {
 	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
 	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
 	int (*setlease)(struct file *, long, struct file_lock **);
+#ifdef CONFIG_NET
+	struct socket *(*get_socket)(struct file *file);
+#endif
 };
 
 struct inode_operations {
diff --git a/net/socket.c b/net/socket.c
index 9dff31c..700efcb 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -119,6 +119,11 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
 			        struct pipe_inode_info *pipe, size_t len,
 				unsigned int flags);
 
+static struct socket *sock_get_socket(struct file *file)
+{
+	return file->private_data;	/* set in sock_map_fd */
+}
+
 /*
  *	Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
  *	in the operation structures but are done directly via the socketcall() multiplexor.
@@ -141,6 +146,7 @@ static const struct file_operations socket_file_ops = {
 	.sendpage =	sock_sendpage,
 	.splice_write = generic_splice_sendpage,
 	.splice_read =	sock_splice_read,
+	.get_socket =   sock_get_socket,
 };
 
 /*
@@ -416,8 +422,8 @@ int sock_map_fd(struct socket *sock, int flags)
 
 static struct socket *sock_from_file(struct file *file, int *err)
 {
-	if (file->f_op == &socket_file_ops)
-		return file->private_data;	/* set in sock_map_fd */
+	if (file->f_op->get_socket)
+		return file->f_op->get_socket(file);
 
 	*err = -ENOTSOCK;
 	return NULL;


-- 
MST

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* Re: [PATCHv6 1/3] tun: export underlying socket
From: Arnd Bergmann @ 2009-11-03 12:41 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtualization, netdev, kvm, linux-kernel, mingo, linux-mm, akpm,
	hpa, gregory.haskins, Rusty Russell, s.hetze
In-Reply-To: <20091103123112.GA4961@redhat.com>

On Tuesday 03 November 2009, Michael S. Tsirkin wrote:
> > What was your reason for changing?
> 
> It turns out socket structure is really bound to specific a file, so we
> can not have 2 files referencing the same socket.  Instead, as I say
> above, it's possible to make sendmsg/recvmsg work on tap file directly.

Ah, I see.

> I have implemented this (patch below), but decided to go with the simple
> thing first.  Since no userspace-visible changes are involved, let's do
> this by small steps: it will be easier to figure out when vhost
> is upstream.

This may even make it easier for me to do the same with macvtap
if I resume work on that.

> @@ -416,8 +422,8 @@ int sock_map_fd(struct socket *sock, int flags)
>  
>  static struct socket *sock_from_file(struct file *file, int *err)
>  {
> -       if (file->f_op == &socket_file_ops)
> -               return file->private_data;      /* set in sock_map_fd */
> +       if (file->f_op->get_socket)
> +               return file->f_op->get_socket(file);
>  
>         *err = -ENOTSOCK;

Or maybe do both (socket_file_ops and get_socket), to avoid an indirect
function call.

	Arnd <><

^ permalink raw reply

* [PATCH]  trivial: remove duplicated MIN macro from tehuti.
From: Thiago Farina @ 2009-11-03 13:10 UTC (permalink / raw)
  To: trivial
  Cc: yanghy, baum, andy, davem, shemminger, apkm, ben, netdev,
	linux-kernel, Thiago Farina

Since the kernel api already has the macro "min",
just use it instead of declaring another one.

Signed-off-by: Thiago Farina <tfransosi@gmail.com>
---
 drivers/net/tehuti.c |    2 +-
 drivers/net/tehuti.h |    2 --
 2 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index ec9dfb2..863084d 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -1878,7 +1878,7 @@ static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size)
 			udelay(50);	/* give hw a chance to clean fifo */
 			continue;
 		}
-		avail = MIN(avail, size);
+		avail = min(avail, size);
 		DBG("about to push  %d bytes starting %p size %d\n", avail,
 		    data, size);
 		bdx_tx_push_desc(priv, data, avail);
diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h
index 4fc875e..1241419 100644
--- a/drivers/net/tehuti.h
+++ b/drivers/net/tehuti.h
@@ -76,8 +76,6 @@
 #define FIFO_SIZE  4096
 #define FIFO_EXTRA_SPACE            1024
 
-#define MIN(x, y)  ((x) < (y) ? (x) : (y))
-
 #if BITS_PER_LONG == 64
 #    define H32_64(x)  (u32) ((u64)(x) >> 32)
 #    define L32_64(x)  (u32) ((u64)(x) & 0xffffffff)
-- 
1.6.5.1.61.ge79999

^ permalink raw reply related

* Re: [PATCH] sch_htb.c consume the classes's tokens bellow the HTB_CAN_SEND level
From: Changli Gao @ 2009-11-03 13:18 UTC (permalink / raw)
  To: Jarek Poplawski; +Cc: Jamal Hadi Salim, devik, netdev
In-Reply-To: <20091103100538.GC6718@ff.dom.local>

On Tue, Nov 3, 2009 at 6:05 PM, Jarek Poplawski <jarkao2@gmail.com> wrote:
>
> The ceil specification is controlled only by ctokens, which are always
> updated, so no such risk.
>
Nevertheless, updating tokens is necessary too.

-- 
Regards,
Changli Gao(xiaosuo@gmail.com)

^ permalink raw reply

* [PATCH net-next-2.6] net: cleanup include/net
From: Eric Dumazet @ 2009-11-03 13:26 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20091103.024424.146854177.davem@davemloft.net>

David Miller a écrit :
> From: Eric Dumazet <eric.dumazet@gmail.com>
>> Would you accept one boring cleanup patch in include/net like following ?
> 
> Absolutely.

Good, here it is.

[PATCH net-next-2.6] net: cleanup include/net

This cleanup patch puts struct/union/enum opening braces,
in first line to ease grep games.

struct something
{

becomes :

struct something {

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
 include/net/ah.h                             |    3 -
 include/net/dn_dev.h                         |   12 ++----
 include/net/dn_fib.h                         |    3 -
 include/net/dn_nsp.h                         |   24 ++++---------
 include/net/dst.h                            |    3 -
 include/net/fib_rules.h                      |    9 +---
 include/net/gen_stats.h                      |    3 -
 include/net/genetlink.h                      |   12 ++----
 include/net/if_inet6.h                       |   24 ++++---------
 include/net/inetpeer.h                       |    3 -
 include/net/ip.h                             |   15 ++------
 include/net/ip6_fib.h                        |   15 ++------
 include/net/ip6_route.h                      |    3 -
 include/net/ip_vs.h                          |    6 +--
 include/net/ipip.h                           |    9 +---
 include/net/ipv6.h                           |   12 ++----
 include/net/iw_handler.h                     |   12 ++----
 include/net/neighbour.h                      |   18 +++------
 include/net/netfilter/nf_conntrack_ecache.h  |    3 -
 include/net/netfilter/nf_conntrack_expect.h  |    6 +--
 include/net/netfilter/nf_conntrack_extend.h  |    6 +--
 include/net/netfilter/nf_conntrack_helper.h  |    3 -
 include/net/netfilter/nf_conntrack_l3proto.h |    3 -
 include/net/netfilter/nf_conntrack_l4proto.h |    3 -
 include/net/netfilter/nf_conntrack_tuple.h   |   12 ++----
 include/net/netfilter/nf_nat.h               |   15 ++------
 include/net/netfilter/nf_nat_protocol.h      |    3 -
 include/net/pkt_cls.h                        |   24 ++++---------
 include/net/pkt_sched.h                      |    3 -
 include/net/protocol.h                       |    3 -
 include/net/red.h                            |    6 +--
 include/net/route.h                          |   12 ++----
 include/net/sch_generic.h                    |   30 +++++-----------
 include/net/scm.h                            |    9 +---
 include/net/sctp/sctp.h                      |    3 -
 include/net/tcp.h                            |    3 -
 include/net/xfrm.h                           |   31 ++++++-----------
 37 files changed, 122 insertions(+), 242 deletions(-)

diff --git a/include/net/ah.h b/include/net/ah.h
index 7573a71..f0129f7 100644
--- a/include/net/ah.h
+++ b/include/net/ah.h
@@ -8,8 +8,7 @@
 
 struct crypto_ahash;
 
-struct ah_data
-{
+struct ah_data {
 	int			icv_full_len;
 	int			icv_trunc_len;
 
diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h
index cee4682..28966ca 100644
--- a/include/net/dn_dev.h
+++ b/include/net/dn_dev.h
@@ -97,16 +97,14 @@ struct dn_dev {
 	unsigned long uptime;     /* Time device went up in jiffies */
 };
 
-struct dn_short_packet
-{
+struct dn_short_packet {
 	__u8    msgflg;
 	__le16 dstnode;
 	__le16 srcnode;
 	__u8   forward;
 } __attribute__((packed));
 
-struct dn_long_packet
-{
+struct dn_long_packet {
 	__u8   msgflg;
 	__u8   d_area;
 	__u8   d_subarea;
@@ -122,8 +120,7 @@ struct dn_long_packet
 
 /*------------------------- DRP - Routing messages ---------------------*/
 
-struct endnode_hello_message
-{
+struct endnode_hello_message {
 	__u8   msgflg;
 	__u8   tiver[3];
 	__u8   id[6];
@@ -138,8 +135,7 @@ struct endnode_hello_message
 	__u8   data[2];
 } __attribute__((packed));
 
-struct rtnode_hello_message
-{
+struct rtnode_hello_message {
 	__u8   msgflg;
 	__u8   tiver[3];
 	__u8   id[6];
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
index c378be7..52da6c3 100644
--- a/include/net/dn_fib.h
+++ b/include/net/dn_fib.h
@@ -4,8 +4,7 @@
 /* WARNING: The ordering of these elements must match ordering
  *          of RTA_* rtnetlink attribute numbers.
  */
-struct dn_kern_rta
-{
+struct dn_kern_rta {
         void            *rta_dst;
         void            *rta_src;
         int             *rta_iif;
diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h
index 96e816b..17d43d2 100644
--- a/include/net/dn_nsp.h
+++ b/include/net/dn_nsp.h
@@ -70,30 +70,26 @@ extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int nobl
 
 /* Data Messages    (data segment/interrupt/link service)               */
 
-struct nsp_data_seg_msg
-{
+struct nsp_data_seg_msg {
 	__u8   msgflg;
 	__le16 dstaddr;
 	__le16 srcaddr;
 } __attribute__((packed));
 
-struct nsp_data_opt_msg
-{
+struct nsp_data_opt_msg {
 	__le16 acknum;
 	__le16 segnum;
 	__le16 lsflgs;
 } __attribute__((packed));
 
-struct nsp_data_opt_msg1
-{
+struct nsp_data_opt_msg1 {
 	__le16 acknum;
 	__le16 segnum;
 } __attribute__((packed));
 
 
 /* Acknowledgment Message (data/other data)                             */
-struct nsp_data_ack_msg
-{
+struct nsp_data_ack_msg {
 	__u8   msgflg;
 	__le16 dstaddr;
 	__le16 srcaddr;
@@ -101,16 +97,14 @@ struct nsp_data_ack_msg
 } __attribute__((packed));
 
 /* Connect Acknowledgment Message */
-struct  nsp_conn_ack_msg
-{
+struct  nsp_conn_ack_msg {
 	__u8 msgflg;
 	__le16 dstaddr;
 } __attribute__((packed));
 
 
 /* Connect Initiate/Retransmit Initiate/Connect Confirm */
-struct  nsp_conn_init_msg
-{
+struct  nsp_conn_init_msg {
 	__u8   msgflg;
 #define NSP_CI      0x18            /* Connect Initiate     */
 #define NSP_RCI     0x68            /* Retrans. Conn Init   */
@@ -126,8 +120,7 @@ struct  nsp_conn_init_msg
 } __attribute__((packed));
 
 /* Disconnect Initiate/Disconnect Confirm */
-struct  nsp_disconn_init_msg
-{
+struct  nsp_disconn_init_msg {
 	__u8   msgflg;
 	__le16 dstaddr;
 	__le16 srcaddr;
@@ -136,8 +129,7 @@ struct  nsp_disconn_init_msg
 
 
 
-struct  srcobj_fmt
-{
+struct  srcobj_fmt {
 	__u8   format;
 	__u8   task;
 	__le16 grpcode;
diff --git a/include/net/dst.h b/include/net/dst.h
index 6377ab2..39c4a59 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -36,8 +36,7 @@
 
 struct sk_buff;
 
-struct dst_entry
-{
+struct dst_entry {
 	struct rcu_head		rcu_head;
 	struct dst_entry	*child;
 	struct net_device       *dev;
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index ca4b2e8..2cd707b 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -7,8 +7,7 @@
 #include <net/flow.h>
 #include <net/rtnetlink.h>
 
-struct fib_rule
-{
+struct fib_rule {
 	struct list_head	list;
 	atomic_t		refcnt;
 	int			ifindex;
@@ -25,15 +24,13 @@ struct fib_rule
 	struct net *		fr_net;
 };
 
-struct fib_lookup_arg
-{
+struct fib_lookup_arg {
 	void			*lookup_ptr;
 	void			*result;
 	struct fib_rule		*rule;
 };
 
-struct fib_rules_ops
-{
+struct fib_rules_ops {
 	int			family;
 	struct list_head	list;
 	int			rule_size;
diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h
index eb87a14..fa15771 100644
--- a/include/net/gen_stats.h
+++ b/include/net/gen_stats.h
@@ -6,8 +6,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/pkt_sched.h>
 
-struct gnet_dump
-{
+struct gnet_dump {
 	spinlock_t *      lock;
 	struct sk_buff *  skb;
 	struct nlattr *   tail;
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 2a1c068..eb551ba 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -13,8 +13,7 @@
  * @list: list entry for linking
  * @family: pointer to family, need not be set before registering
  */
-struct genl_multicast_group
-{
+struct genl_multicast_group {
 	struct genl_family	*family;	/* private */
 	struct list_head	list;		/* private */
 	char			name[GENL_NAMSIZ];
@@ -35,8 +34,7 @@ struct genl_multicast_group
  * @family_list: family list
  * @mcast_groups: multicast groups list
  */
-struct genl_family
-{
+struct genl_family {
 	unsigned int		id;
 	unsigned int		hdrsize;
 	char			name[GENL_NAMSIZ];
@@ -58,8 +56,7 @@ struct genl_family
  * @userhdr: user specific header
  * @attrs: netlink attributes
  */
-struct genl_info
-{
+struct genl_info {
 	u32			snd_seq;
 	u32			snd_pid;
 	struct nlmsghdr *	nlhdr;
@@ -102,8 +99,7 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net)
  * @done: completion callback for dumps
  * @ops_list: operations list
  */
-struct genl_ops
-{
+struct genl_ops {
 	u8			cmd;
 	unsigned int		flags;
 	const struct nla_policy	*policy;
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 38b7813..e9d69d1 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -32,8 +32,7 @@
 
 #ifdef __KERNEL__
 
-struct inet6_ifaddr 
-{
+struct inet6_ifaddr {
 	struct in6_addr		addr;
 	__u32			prefix_len;
 	
@@ -67,8 +66,7 @@ struct inet6_ifaddr
 	int			dead;
 };
 
-struct ip6_sf_socklist
-{
+struct ip6_sf_socklist {
 	unsigned int		sl_max;
 	unsigned int		sl_count;
 	struct in6_addr		sl_addr[0];
@@ -79,8 +77,7 @@ struct ip6_sf_socklist
 
 #define IP6_SFBLOCK	10	/* allocate this many at once */
 
-struct ipv6_mc_socklist
-{
+struct ipv6_mc_socklist {
 	struct in6_addr		addr;
 	int			ifindex;
 	struct ipv6_mc_socklist *next;
@@ -89,8 +86,7 @@ struct ipv6_mc_socklist
 	struct ip6_sf_socklist	*sflist;
 };
 
-struct ip6_sf_list
-{
+struct ip6_sf_list {
 	struct ip6_sf_list	*sf_next;
 	struct in6_addr		sf_addr;
 	unsigned long		sf_count[2];	/* include/exclude counts */
@@ -105,8 +101,7 @@ struct ip6_sf_list
 #define MAF_NOREPORT		0x08
 #define MAF_GSQUERY		0x10
 
-struct ifmcaddr6
-{
+struct ifmcaddr6 {
 	struct in6_addr		mca_addr;
 	struct inet6_dev	*idev;
 	struct ifmcaddr6	*next;
@@ -126,15 +121,13 @@ struct ifmcaddr6
 
 /* Anycast stuff */
 
-struct ipv6_ac_socklist
-{
+struct ipv6_ac_socklist {
 	struct in6_addr		acl_addr;
 	int			acl_ifindex;
 	struct ipv6_ac_socklist *acl_next;
 };
 
-struct ifacaddr6
-{
+struct ifacaddr6 {
 	struct in6_addr		aca_addr;
 	struct inet6_dev	*aca_idev;
 	struct rt6_info		*aca_rt;
@@ -157,8 +150,7 @@ struct ipv6_devstat {
 	DEFINE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg);
 };
 
-struct inet6_dev 
-{
+struct inet6_dev {
 	struct net_device		*dev;
 
 	struct inet6_ifaddr	*addr_list;
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 15e1f8f..35ad7b9 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -13,8 +13,7 @@
 #include <linux/spinlock.h>
 #include <asm/atomic.h>
 
-struct inet_peer
-{
+struct inet_peer {
 	/* group together avl_left,avl_right,v4daddr to speedup lookups */
 	struct inet_peer	*avl_left, *avl_right;
 	__be32			v4daddr;	/* peer's address */
diff --git a/include/net/ip.h b/include/net/ip.h
index 376adf4..e6b9d12 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -33,8 +33,7 @@
 
 struct sock;
 
-struct inet_skb_parm
-{
+struct inet_skb_parm {
 	struct ip_options	opt;		/* Compiled IP options		*/
 	unsigned char		flags;
 
@@ -50,8 +49,7 @@ static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
 	return ip_hdr(skb)->ihl * 4;
 }
 
-struct ipcm_cookie
-{
+struct ipcm_cookie {
 	__be32			addr;
 	int			oif;
 	struct ip_options	*opt;
@@ -60,8 +58,7 @@ struct ipcm_cookie
 
 #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
 
-struct ip_ra_chain
-{
+struct ip_ra_chain {
 	struct ip_ra_chain	*next;
 	struct sock		*sk;
 	void			(*destructor)(struct sock *);
@@ -159,8 +156,7 @@ static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
 void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
 		   unsigned int len); 
 
-struct ipv4_config
-{
+struct ipv4_config {
 	int	log_martians;
 	int	no_pmtu_disc;
 };
@@ -336,8 +332,7 @@ extern int	ip_call_ra_chain(struct sk_buff *skb);
  *	Functions provided by ip_fragment.c
  */
 
-enum ip_defrag_users
-{
+enum ip_defrag_users {
 	IP_DEFRAG_LOCAL_DELIVER,
 	IP_DEFRAG_CALL_RA_CHAIN,
 	IP_DEFRAG_CONNTRACK_IN,
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 15b492a..2578081 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -30,8 +30,7 @@
 
 struct rt6_info;
 
-struct fib6_config
-{
+struct fib6_config {
 	u32		fc_table;
 	u32		fc_metric;
 	int		fc_dst_len;
@@ -51,8 +50,7 @@ struct fib6_config
 	struct nl_info	fc_nlinfo;
 };
 
-struct fib6_node
-{
+struct fib6_node {
 	struct fib6_node	*parent;
 	struct fib6_node	*left;
 	struct fib6_node	*right;
@@ -78,16 +76,14 @@ struct fib6_node
  *
  */
 
-struct rt6key
-{
+struct rt6key {
 	struct in6_addr	addr;
 	int		plen;
 };
 
 struct fib6_table;
 
-struct rt6_info
-{
+struct rt6_info {
 	union {
 		struct dst_entry	dst;
 	} u;
@@ -127,8 +123,7 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
 	return ((struct rt6_info *)dst)->rt6i_idev;
 }
 
-struct fib6_walker_t
-{
+struct fib6_walker_t {
 	struct fib6_walker_t *prev, *next;
 	struct fib6_node *root, *node;
 	struct rt6_info *leaf;
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 0e1b8ae..4a808de 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -103,8 +103,7 @@ extern void			rt6_pmtu_discovery(struct in6_addr *daddr,
 
 struct netlink_callback;
 
-struct rt6_rtnl_dump_arg
-{
+struct rt6_rtnl_dump_arg {
 	struct sk_buff *skb;
 	struct netlink_callback *cb;
 	struct net *net;
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 98978e7..8dc3296 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -251,8 +251,7 @@ struct ip_vs_estimator {
 	u32			outbps;
 };
 
-struct ip_vs_stats
-{
+struct ip_vs_stats {
 	struct ip_vs_stats_user	ustats;         /* statistics */
 	struct ip_vs_estimator	est;		/* estimator */
 
@@ -518,8 +517,7 @@ struct ip_vs_scheduler {
 /*
  *	The application module object (a.k.a. app incarnation)
  */
-struct ip_vs_app
-{
+struct ip_vs_app {
 	struct list_head	a_list;		/* member in app list */
 	int			type;		/* IP_VS_APP_TYPE_xxx */
 	char			*name;		/* application module name */
diff --git a/include/net/ipip.h b/include/net/ipip.h
index b3db2fd..11e8513 100644
--- a/include/net/ipip.h
+++ b/include/net/ipip.h
@@ -8,16 +8,14 @@
 #define IPTUNNEL_ERR_TIMEO	(30*HZ)
 
 /* 6rd prefix/relay information */
-struct ip_tunnel_6rd_parm
-{
+struct ip_tunnel_6rd_parm {
 	struct in6_addr		prefix;
 	__be32			relay_prefix;
 	u16			prefixlen;
 	u16			relay_prefixlen;
 };
 
-struct ip_tunnel
-{
+struct ip_tunnel {
 	struct ip_tunnel	*next;
 	struct net_device	*dev;
 
@@ -40,8 +38,7 @@ struct ip_tunnel
 	unsigned int			prl_count;	/* # of entries in PRL */
 };
 
-struct ip_tunnel_prl_entry
-{
+struct ip_tunnel_prl_entry {
 	struct ip_tunnel_prl_entry	*next;
 	__be32				addr;
 	u16				flags;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 8c31d8a..92db861 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -160,8 +160,7 @@ extern struct ctl_path net_ipv6_ctl_path[];
 #define ICMP6MSGIN_INC_STATS_BH(net, idev, field)	\
 	_DEVINC(net, icmpv6msg, _BH, idev, field)
 
-struct ip6_ra_chain
-{
+struct ip6_ra_chain {
 	struct ip6_ra_chain	*next;
 	struct sock		*sk;
 	int			sel;
@@ -176,8 +175,7 @@ extern rwlock_t ip6_ra_lock;
    ancillary data and passed to IPv6.
  */
 
-struct ipv6_txoptions
-{
+struct ipv6_txoptions {
 	/* Length of this structure */
 	int			tot_len;
 
@@ -194,8 +192,7 @@ struct ipv6_txoptions
 	/* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */
 };
 
-struct ip6_flowlabel
-{
+struct ip6_flowlabel {
 	struct ip6_flowlabel	*next;
 	__be32			label;
 	atomic_t		users;
@@ -212,8 +209,7 @@ struct ip6_flowlabel
 #define IPV6_FLOWINFO_MASK	cpu_to_be32(0x0FFFFFFF)
 #define IPV6_FLOWLABEL_MASK	cpu_to_be32(0x000FFFFF)
 
-struct ipv6_fl_socklist
-{
+struct ipv6_fl_socklist {
 	struct ipv6_fl_socklist	*next;
 	struct ip6_flowlabel	*fl;
 };
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index d5d3371..b2b98f3 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -300,8 +300,7 @@
  * This struct is also my long term insurance. I can add new fields here
  * without breaking the prototype of iw_handler...
  */
-struct iw_request_info
-{
+struct iw_request_info {
 	__u16		cmd;		/* Wireless Extension command */
 	__u16		flags;		/* More to come ;-) */
 };
@@ -321,8 +320,7 @@ typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
  * shared by all driver instances... Same for the members...
  * This will be linked from net_device in <linux/netdevice.h>
  */
-struct iw_handler_def
-{
+struct iw_handler_def {
 
 	/* Array of handlers for standard ioctls
 	 * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT]
@@ -372,8 +370,7 @@ struct iw_handler_def
 /*
  * Describe how a standard IOCTL looks like.
  */
-struct iw_ioctl_description
-{
+struct iw_ioctl_description {
 	__u8	header_type;		/* NULL, iw_point or other */
 	__u8	token_type;		/* Future */
 	__u16	token_size;		/* Granularity of payload */
@@ -395,8 +392,7 @@ struct iw_ioctl_description
 /*
  * Instance specific spy data, i.e. addresses spied and quality for them.
  */
-struct iw_spy_data
-{
+struct iw_spy_data {
 	/* --- Standard spy support --- */
 	int			spy_number;
 	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 3817fda..db8e96d 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -37,8 +37,7 @@
 
 struct neighbour;
 
-struct neigh_parms
-{
+struct neigh_parms {
 #ifdef CONFIG_NET_NS
 	struct net *net;
 #endif
@@ -70,8 +69,7 @@ struct neigh_parms
 	int	locktime;
 };
 
-struct neigh_statistics
-{
+struct neigh_statistics {
 	unsigned long allocs;		/* number of allocated neighs */
 	unsigned long destroys;		/* number of destroyed neighs */
 	unsigned long hash_grows;	/* number of hash resizes */
@@ -97,8 +95,7 @@ struct neigh_statistics
 		preempt_enable();					\
 	} while (0)
 
-struct neighbour
-{
+struct neighbour {
 	struct neighbour	*next;
 	struct neigh_table	*tbl;
 	struct neigh_parms	*parms;
@@ -122,8 +119,7 @@ struct neighbour
 	u8			primary_key[0];
 };
 
-struct neigh_ops
-{
+struct neigh_ops {
 	int			family;
 	void			(*solicit)(struct neighbour *, struct sk_buff*);
 	void			(*error_report)(struct neighbour *, struct sk_buff*);
@@ -133,8 +129,7 @@ struct neigh_ops
 	int			(*queue_xmit)(struct sk_buff*);
 };
 
-struct pneigh_entry
-{
+struct pneigh_entry {
 	struct pneigh_entry	*next;
 #ifdef CONFIG_NET_NS
 	struct net		*net;
@@ -149,8 +144,7 @@ struct pneigh_entry
  */
 
 
-struct neigh_table
-{
+struct neigh_table {
 	struct neigh_table	*next;
 	int			family;
 	int			entry_size;
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 4f20d58..475facc 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -13,8 +13,7 @@
 #include <net/netfilter/nf_conntrack_extend.h>
 
 /* Connection tracking event types */
-enum ip_conntrack_events
-{
+enum ip_conntrack_events {
 	IPCT_NEW		= 0,	/* new conntrack */
 	IPCT_RELATED		= 1,	/* related conntrack */
 	IPCT_DESTROY		= 2,	/* destroyed conntrack */
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index a965280..9a2b9cb 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -9,8 +9,7 @@
 extern unsigned int nf_ct_expect_hsize;
 extern unsigned int nf_ct_expect_max;
 
-struct nf_conntrack_expect
-{
+struct nf_conntrack_expect {
 	/* Conntrack expectation list member */
 	struct hlist_node lnode;
 
@@ -64,8 +63,7 @@ static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp)
 #endif
 }
 
-struct nf_conntrack_expect_policy
-{
+struct nf_conntrack_expect_policy {
 	unsigned int	max_expected;
 	unsigned int	timeout;
 };
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
index 7f8fc5d..e192dc1 100644
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -3,8 +3,7 @@
 
 #include <net/netfilter/nf_conntrack.h>
 
-enum nf_ct_ext_id
-{
+enum nf_ct_ext_id {
 	NF_CT_EXT_HELPER,
 	NF_CT_EXT_NAT,
 	NF_CT_EXT_ACCT,
@@ -65,8 +64,7 @@ __nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);
 
 #define NF_CT_EXT_F_PREALLOC	0x0001
 
-struct nf_ct_ext_type
-{
+struct nf_ct_ext_type {
 	/* Destroys relationships (can be NULL). */
 	void (*destroy)(struct nf_conn *ct);
 	/* Called when realloacted (can be NULL).
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 1b70680..d015de9 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -16,8 +16,7 @@ struct module;
 
 #define NF_CT_HELPER_NAME_LEN	16
 
-struct nf_conntrack_helper
-{
+struct nf_conntrack_helper {
 	struct hlist_node hnode;	/* Internal use. */
 
 	const char *name;		/* name of the module */
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index 9f99d36..a754761 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -16,8 +16,7 @@
 #include <linux/seq_file.h>
 #include <net/netfilter/nf_conntrack.h>
 
-struct nf_conntrack_l3proto
-{
+struct nf_conntrack_l3proto {
 	/* L3 Protocol Family number. ex) PF_INET */
 	u_int16_t l3proto;
 
diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h
index 3767fb4..ca6dcf3 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -15,8 +15,7 @@
 
 struct seq_file;
 
-struct nf_conntrack_l4proto
-{
+struct nf_conntrack_l4proto {
 	/* L3 Protocol number. */
 	u_int16_t l3proto;
 
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 2628c15..4ee44c8 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -26,8 +26,7 @@
 
 /* The protocol-specific manipulable parts of the tuple: always in
    network order! */
-union nf_conntrack_man_proto
-{
+union nf_conntrack_man_proto {
 	/* Add other protocols here. */
 	__be16 all;
 
@@ -52,8 +51,7 @@ union nf_conntrack_man_proto
 };
 
 /* The manipulable part of the tuple. */
-struct nf_conntrack_man
-{
+struct nf_conntrack_man {
 	union nf_inet_addr u3;
 	union nf_conntrack_man_proto u;
 	/* Layer 3 protocol */
@@ -61,8 +59,7 @@ struct nf_conntrack_man
 };
 
 /* This contains the information to distinguish a connection. */
-struct nf_conntrack_tuple
-{
+struct nf_conntrack_tuple {
 	struct nf_conntrack_man src;
 
 	/* These are the parts of the tuple which are fixed. */
@@ -100,8 +97,7 @@ struct nf_conntrack_tuple
 	} dst;
 };
 
-struct nf_conntrack_tuple_mask
-{
+struct nf_conntrack_tuple_mask {
 	struct {
 		union nf_inet_addr u3;
 		union nf_conntrack_man_proto u;
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index 8df0b7f..f5f09f0 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -5,8 +5,7 @@
 
 #define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16
 
-enum nf_nat_manip_type
-{
+enum nf_nat_manip_type {
 	IP_NAT_MANIP_SRC,
 	IP_NAT_MANIP_DST
 };
@@ -30,8 +29,7 @@ struct nf_nat_seq {
 };
 
 /* Single range specification. */
-struct nf_nat_range
-{
+struct nf_nat_range {
 	/* Set to OR of flags above. */
 	unsigned int flags;
 
@@ -43,8 +41,7 @@ struct nf_nat_range
 };
 
 /* For backwards compat: don't use in modern code. */
-struct nf_nat_multi_range_compat
-{
+struct nf_nat_multi_range_compat {
 	unsigned int rangesize; /* Must be 1. */
 
 	/* hangs off end. */
@@ -57,8 +54,7 @@ struct nf_nat_multi_range_compat
 #include <net/netfilter/nf_conntrack_extend.h>
 
 /* per conntrack: nat application helper private data */
-union nf_conntrack_nat_help
-{
+union nf_conntrack_nat_help {
 	/* insert nat helper private data here */
 	struct nf_nat_pptp nat_pptp_info;
 };
@@ -66,8 +62,7 @@ union nf_conntrack_nat_help
 struct nf_conn;
 
 /* The structure embedded in the conntrack structure. */
-struct nf_conn_nat
-{
+struct nf_conn_nat {
 	struct hlist_node bysource;
 	struct nf_nat_seq seq[IP_CT_DIR_MAX];
 	struct nf_conn *ct;
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
index f3662c4..c398017 100644
--- a/include/net/netfilter/nf_nat_protocol.h
+++ b/include/net/netfilter/nf_nat_protocol.h
@@ -6,8 +6,7 @@
 
 struct nf_nat_range;
 
-struct nf_nat_protocol
-{
+struct nf_nat_protocol {
 	/* Protocol number. */
 	unsigned int protonum;
 
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index d1ca314..3dd210d 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -7,8 +7,7 @@
 
 /* Basic packet classifier frontend definitions. */
 
-struct tcf_walker
-{
+struct tcf_walker {
 	int	stop;
 	int	skip;
 	int	count;
@@ -61,8 +60,7 @@ tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
 		tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
 }
 
-struct tcf_exts
-{
+struct tcf_exts {
 #ifdef CONFIG_NET_CLS_ACT
 	struct tc_action *action;
 #endif
@@ -71,8 +69,7 @@ struct tcf_exts
 /* Map to export classifier specific extension TLV types to the
  * generic extensions API. Unsupported extensions must be set to 0.
  */
-struct tcf_ext_map
-{
+struct tcf_ext_map {
 	int action;
 	int police;
 };
@@ -143,8 +140,7 @@ extern int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
 /**
  * struct tcf_pkt_info - packet information
  */
-struct tcf_pkt_info
-{
+struct tcf_pkt_info {
 	unsigned char *		ptr;
 	int			nexthdr;
 };
@@ -162,8 +158,7 @@ struct tcf_ematch_ops;
  * @datalen: length of the ematch specific configuration data
  * @data: ematch specific data
  */
-struct tcf_ematch
-{
+struct tcf_ematch {
 	struct tcf_ematch_ops * ops;
 	unsigned long		data;
 	unsigned int		datalen;
@@ -211,8 +206,7 @@ static inline int tcf_em_early_end(struct tcf_ematch *em, int result)
  * @hdr: ematch tree header supplied by userspace
  * @matches: array of ematches
  */
-struct tcf_ematch_tree
-{
+struct tcf_ematch_tree {
 	struct tcf_ematch_tree_hdr hdr;
 	struct tcf_ematch *	matches;
 	
@@ -230,8 +224,7 @@ struct tcf_ematch_tree
  * @owner: owner, must be set to THIS_MODULE
  * @link: link to previous/next ematch module (internal use)
  */
-struct tcf_ematch_ops
-{
+struct tcf_ematch_ops {
 	int			kind;
 	int			datalen;
 	int			(*change)(struct tcf_proto *, void *,
@@ -302,8 +295,7 @@ static inline int tcf_em_tree_match(struct sk_buff *skb,
 
 #else /* CONFIG_NET_EMATCH */
 
-struct tcf_ematch_tree
-{
+struct tcf_ematch_tree {
 };
 
 #define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0)
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index f911ec7..2d56726 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -5,8 +5,7 @@
 #include <linux/ktime.h>
 #include <net/sch_generic.h>
 
-struct qdisc_walker
-{
+struct qdisc_walker {
 	int	stop;
 	int	skip;
 	int	count;
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 60249e5..89932d4 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -47,8 +47,7 @@ struct net_protocol {
 };
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-struct inet6_protocol 
-{
+struct inet6_protocol {
 	int	(*handler)(struct sk_buff *skb);
 
 	void	(*err_handler)(struct sk_buff *skb,
diff --git a/include/net/red.h b/include/net/red.h
index 3cf31d4..995108e 100644
--- a/include/net/red.h
+++ b/include/net/red.h
@@ -90,8 +90,7 @@
 #define RED_STAB_SIZE	256
 #define RED_STAB_MASK	(RED_STAB_SIZE - 1)
 
-struct red_stats
-{
+struct red_stats {
 	u32		prob_drop;	/* Early probability drops */
 	u32		prob_mark;	/* Early probability marks */
 	u32		forced_drop;	/* Forced drops, qavg > max_thresh */
@@ -101,8 +100,7 @@ struct red_stats
 	u32		backlog;
 };
 
-struct red_parms
-{
+struct red_parms {
 	/* Parameters */
 	u32		qth_min;	/* Min avg length threshold: A scaled */
 	u32		qth_max;	/* Max avg length threshold: A scaled */
diff --git a/include/net/route.h b/include/net/route.h
index 40f6346..cfb4c07 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -49,10 +49,8 @@
 
 struct fib_nh;
 struct inet_peer;
-struct rtable
-{
-	union
-	{
+struct rtable {
+	union {
 		struct dst_entry	dst;
 	} u;
 
@@ -77,16 +75,14 @@ struct rtable
 	struct inet_peer	*peer; /* long-living peer info */
 };
 
-struct ip_rt_acct
-{
+struct ip_rt_acct {
 	__u32 	o_bytes;
 	__u32 	o_packets;
 	__u32 	i_bytes;
 	__u32 	i_packets;
 };
 
-struct rt_cache_stat 
-{
+struct rt_cache_stat {
         unsigned int in_hit;
         unsigned int in_slow_tot;
         unsigned int in_slow_mc;
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index c33180d..dad558b 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -15,16 +15,14 @@ struct qdisc_walker;
 struct tcf_walker;
 struct module;
 
-struct qdisc_rate_table
-{
+struct qdisc_rate_table {
 	struct tc_ratespec rate;
 	u32		data[256];
 	struct qdisc_rate_table *next;
 	int		refcnt;
 };
 
-enum qdisc_state_t
-{
+enum qdisc_state_t {
 	__QDISC_STATE_RUNNING,
 	__QDISC_STATE_SCHED,
 	__QDISC_STATE_DEACTIVATED,
@@ -37,8 +35,7 @@ struct qdisc_size_table {
 	u16			data[];
 };
 
-struct Qdisc
-{
+struct Qdisc {
 	int 			(*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
 	struct sk_buff *	(*dequeue)(struct Qdisc *dev);
 	unsigned		flags;
@@ -78,8 +75,7 @@ struct Qdisc
 	struct gnet_stats_queue	qstats;
 };
 
-struct Qdisc_class_ops
-{
+struct Qdisc_class_ops {
 	/* Child qdisc manipulation */
 	struct netdev_queue *	(*select_queue)(struct Qdisc *, struct tcmsg *);
 	int			(*graft)(struct Qdisc *, unsigned long cl,
@@ -108,8 +104,7 @@ struct Qdisc_class_ops
 					struct gnet_dump *);
 };
 
-struct Qdisc_ops
-{
+struct Qdisc_ops {
 	struct Qdisc_ops	*next;
 	const struct Qdisc_class_ops	*cl_ops;
 	char			id[IFNAMSIZ];
@@ -133,14 +128,12 @@ struct Qdisc_ops
 };
 
 
-struct tcf_result
-{
+struct tcf_result {
 	unsigned long	class;
 	u32		classid;
 };
 
-struct tcf_proto_ops
-{
+struct tcf_proto_ops {
 	struct tcf_proto_ops	*next;
 	char			kind[IFNAMSIZ];
 
@@ -164,8 +157,7 @@ struct tcf_proto_ops
 	struct module		*owner;
 };
 
-struct tcf_proto
-{
+struct tcf_proto {
 	/* Fast access part */
 	struct tcf_proto	*next;
 	void			*root;
@@ -261,14 +253,12 @@ extern struct Qdisc_ops noop_qdisc_ops;
 extern struct Qdisc_ops pfifo_fast_ops;
 extern struct Qdisc_ops mq_qdisc_ops;
 
-struct Qdisc_class_common
-{
+struct Qdisc_class_common {
 	u32			classid;
 	struct hlist_node	hnode;
 };
 
-struct Qdisc_class_hash
-{
+struct Qdisc_class_hash {
 	struct hlist_head	*hash;
 	unsigned int		hashsize;
 	unsigned int		hashmask;
diff --git a/include/net/scm.h b/include/net/scm.h
index cf48c80..8360e47 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -12,15 +12,13 @@
  */
 #define SCM_MAX_FD	255
 
-struct scm_fp_list
-{
+struct scm_fp_list {
 	struct list_head	list;
 	int			count;
 	struct file		*fp[SCM_MAX_FD];
 };
 
-struct scm_cookie
-{
+struct scm_cookie {
 	struct ucred		creds;		/* Skb credentials	*/
 	struct scm_fp_list	*fp;		/* Passed files		*/
 #ifdef CONFIG_SECURITY_NETWORK
@@ -88,8 +86,7 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc
 static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
 				struct scm_cookie *scm, int flags)
 {
-	if (!msg->msg_control)
-	{
+	if (!msg->msg_control) {
 		if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
 			msg->msg_flags |= MSG_CTRUNC;
 		scm_destroy(scm);
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 8a6d529..78740ec 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -227,8 +227,7 @@ DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics);
 #endif /* !TEST_FRAME */
 
 /* sctp mib definitions */
-enum
-{
+enum {
 	SCTP_MIB_NUM = 0,
 	SCTP_MIB_CURRESTAB,			/* CurrEstab */
 	SCTP_MIB_ACTIVEESTABS,			/* ActiveEstabs */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 740d09b..bf20f88 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -359,8 +359,7 @@ TCP_ECN_create_request(struct request_sock *req, struct tcphdr *th)
 		inet_rsk(req)->ecn_ok = 1;
 }
 
-enum tcp_tw_status
-{
+enum tcp_tw_status {
 	TCP_TW_SUCCESS = 0,
 	TCP_TW_RST = 1,
 	TCP_TW_ACK = 2,
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index d9c6dbb..6d55b36 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -121,8 +121,7 @@ struct xfrm_state_walk {
 };
 
 /* Full description of state of transformer. */
-struct xfrm_state
-{
+struct xfrm_state {
 #ifdef CONFIG_NET_NS
 	struct net		*xs_net;
 #endif
@@ -237,8 +236,7 @@ enum {
 };
 
 /* callback structure passed from either netlink or pfkey */
-struct km_event
-{
+struct km_event {
 	union {
 		u32 hard;
 		u32 proto;
@@ -313,8 +311,7 @@ extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
 
 extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
-struct xfrm_type
-{
+struct xfrm_type {
 	char			*description;
 	struct module		*owner;
 	__u8			proto;
@@ -420,8 +417,7 @@ static inline struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipp
 		return x->inner_mode_iaf;
 }
 
-struct xfrm_tmpl
-{
+struct xfrm_tmpl {
 /* id in template is interpreted as:
  * daddr - destination of tunnel, may be zero for transport mode.
  * spi   - zero to acquire spi. Not zero if spi is static, then
@@ -468,8 +464,7 @@ struct xfrm_policy_walk {
 	u32 seq;
 };
 
-struct xfrm_policy
-{
+struct xfrm_policy {
 #ifdef CONFIG_NET_NS
 	struct net		*xp_net;
 #endif
@@ -538,8 +533,7 @@ struct xfrm_migrate {
 /* default seq threshold size */
 #define XFRM_AE_SEQT_SIZE		2
 
-struct xfrm_mgr
-{
+struct xfrm_mgr {
 	struct list_head	list;
 	char			*id;
 	int			(*notify)(struct xfrm_state *x, struct km_event *c);
@@ -626,8 +620,7 @@ struct xfrm_spi_skb_cb {
 #define XFRM_SPI_SKB_CB(__skb) ((struct xfrm_spi_skb_cb *)&((__skb)->cb[0]))
 
 /* Audit Information */
-struct xfrm_audit
-{
+struct xfrm_audit {
 	u32	secid;
 	uid_t	loginuid;
 	u32	sessionid;
@@ -871,8 +864,7 @@ static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ct
  * bundles differing by session id. All the bundles grow from a parent
  * policy rule.
  */
-struct xfrm_dst
-{
+struct xfrm_dst {
 	union {
 		struct dst_entry	dst;
 		struct rtable		rt;
@@ -907,8 +899,7 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
 
 extern void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev);
 
-struct sec_path
-{
+struct sec_path {
 	atomic_t		refcnt;
 	int			len;
 	struct xfrm_state	*xvec[XFRM_MAX_DEPTH];

^ permalink raw reply related

* [PATCH 7/13] macsonic: fix crash on PowerBook 520
From: Finn Thain @ 2009-11-03 13:42 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: Thomas Bogendoerfer, netdev, linux-m68k

No-one seems to know where the PowerBook 500 series store their ethernet 
MAC addresses. So, rather than crash, use a MAC address from the SONIC 
CAM. Failing that, generate a random one.

Signed-off-by: Finn Thain <fthain@telegraphics.com.au>

---
 drivers/net/macsonic.c |  113 +++++++++++++++++++++++++------------------------
 1 file changed, 58 insertions(+), 55 deletions(-)

Index: linux-2.6.31/drivers/net/macsonic.c
===================================================================
--- linux-2.6.31.orig/drivers/net/macsonic.c	2009-11-03 03:23:42.000000000 +1100
+++ linux-2.6.31/drivers/net/macsonic.c	2009-11-03 03:23:42.000000000 +1100
@@ -222,69 +222,73 @@ static int __devinit macsonic_init(struc
 	return 0;
 }
 
-static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
+#define INVALID_MAC(mac) (memcmp(mac, "\x08\x00\x07", 3) && \
+                          memcmp(mac, "\x00\xA0\x40", 3) && \
+                          memcmp(mac, "\x00\x80\x19", 3) && \
+                          memcmp(mac, "\x00\x05\x02", 3))
+
+static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
 {
 	struct sonic_local *lp = netdev_priv(dev);
 	const int prom_addr = ONBOARD_SONIC_PROM_BASE;
-	int i;
+	unsigned short val;
 
-	/* On NuBus boards we can sometimes look in the ROM resources.
-	   No such luck for comm-slot/onboard. */
-	for(i = 0; i < 6; i++)
-		dev->dev_addr[i] = SONIC_READ_PROM(i);
+	/*
+	 * On NuBus boards we can sometimes look in the ROM resources.
+	 * No such luck for comm-slot/onboard.
+	 * On the PowerBook 520, the PROM base address is a mystery.
+	 */
+	if (hwreg_present((void *)prom_addr)) {
+		int i;
+
+		for (i = 0; i < 6; i++)
+			dev->dev_addr[i] = SONIC_READ_PROM(i);
+		if (!INVALID_MAC(dev->dev_addr))
+			return;
 
-	/* Most of the time, the address is bit-reversed.  The NetBSD
-	   source has a rather long and detailed historical account of
-	   why this is so. */
-	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
-	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
-	    memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
-	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+		/*
+		 * Most of the time, the address is bit-reversed. The NetBSD
+		 * source has a rather long and detailed historical account of
+		 * why this is so.
+		 */
 		bit_reverse_addr(dev->dev_addr);
-	else
-		return 0;
+		if (!INVALID_MAC(dev->dev_addr))
+			return;
 
-	/* If we still have what seems to be a bogus address, we'll
-           look in the CAM.  The top entry should be ours. */
-	/* Danger! This only works if MacOS has already initialized
-           the card... */
-	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
-	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
-	    memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
-	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
-	{
-		unsigned short val;
+		/*
+		 * If we still have what seems to be a bogus address, we'll
+		 * look in the CAM. The top entry should be ours.
+		 */
+		printk(KERN_WARNING "macsonic: MAC address in PROM seems "
+		                    "to be invalid, trying CAM\n");
+	} else {
+		printk(KERN_WARNING "macsonic: cannot read MAC address from "
+		                    "PROM, trying CAM\n");
+	}
 
-		printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n");
+	/* This only works if MacOS has already initialized the card. */
 
-		SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
-		SONIC_WRITE(SONIC_CEP, 15);
+	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+	SONIC_WRITE(SONIC_CEP, 15);
 
-		val = SONIC_READ(SONIC_CAP2);
-		dev->dev_addr[5] = val >> 8;
-		dev->dev_addr[4] = val & 0xff;
-		val = SONIC_READ(SONIC_CAP1);
-		dev->dev_addr[3] = val >> 8;
-		dev->dev_addr[2] = val & 0xff;
-		val = SONIC_READ(SONIC_CAP0);
-		dev->dev_addr[1] = val >> 8;
-		dev->dev_addr[0] = val & 0xff;
-
-		printk(KERN_INFO "HW Address from CAM 15: %pM\n",
-		       dev->dev_addr);
-	} else return 0;
-
-	if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
-	    memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
-	    memcmp(dev->dev_addr, "\x00\x80\x19", 3) &&
-	    memcmp(dev->dev_addr, "\x00\x05\x02", 3))
-	{
-		/*
-		 * Still nonsense ... messed up someplace!
-		 */
-		printk(KERN_ERR "macsonic: ERROR (INVALID MAC)\n");
-		return -EIO;
-	} else return 0;
+	val = SONIC_READ(SONIC_CAP2);
+	dev->dev_addr[5] = val >> 8;
+	dev->dev_addr[4] = val & 0xff;
+	val = SONIC_READ(SONIC_CAP1);
+	dev->dev_addr[3] = val >> 8;
+	dev->dev_addr[2] = val & 0xff;
+	val = SONIC_READ(SONIC_CAP0);
+	dev->dev_addr[1] = val >> 8;
+	dev->dev_addr[0] = val & 0xff;
+
+	if (!INVALID_MAC(dev->dev_addr))
+		return;
+
+	/* Still nonsense ... messed up someplace! */
+
+	printk(KERN_WARNING "macsonic: MAC address in CAM entry 15 "
+	                    "seems invalid, will use a random MAC\n");
+	random_ether_addr(dev->dev_addr);
 }
 
 static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
@@ -401,8 +405,7 @@ static int __devinit mac_onboard_sonic_p
 	SONIC_WRITE(SONIC_ISR, 0x7fff);
 
 	/* Now look for the MAC address. */
-	if (mac_onboard_sonic_ethernet_addr(dev) != 0)
-		return -ENODEV;
+	mac_onboard_sonic_ethernet_addr(dev);
 
 	/* Shared init code */
 	return macsonic_init(dev);

^ permalink raw reply

* Re: [PATCHv2] tun: export underlying socket
From: Herbert Xu @ 2009-11-03 15:10 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: David Miller, Eric Dumazet, Paul Moore, netdev
In-Reply-To: <20091102172022.GA28247@redhat.com>

On Mon, Nov 02, 2009 at 07:20:22PM +0200, Michael S. Tsirkin wrote:
> Tun device looks similar to a packet socket
> in that both pass complete frames from/to userspace.
> 
> This patch fills in enough fields in the socket underlying tun driver
> to support sendmsg/recvmsg operations, and message flags
> MSG_TRUNC and MSG_DONTWAIT, and exports access to this socket
> to modules.  Regular read/write behaviour is unchanged.
> 
> This way, code using raw sockets to inject packets
> into a physical device, can support injecting
> packets into host network stack almost without modification.
> 
> First user of this interface will be vhost virtualization
> accelerator.
> 
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [PATCH 1/3] sysfs directory scaling: rbtree for dirent name lookups
From: Greg KH @ 2009-11-03 16:07 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Benjamin LaHaise, Eric W. Biederman, Octavian Purdila, netdev,
	Cosmin Ratiu, linux-kernel
In-Reply-To: <4AEFCA49.4020305@gmail.com>

On Tue, Nov 03, 2009 at 07:14:33AM +0100, Eric Dumazet wrote:
> Greg KH a ?crit :
> > On Sun, Nov 01, 2009 at 11:31:30AM -0500, Benjamin LaHaise wrote:
> >> Use an rbtree in sysfs_dirent to speed up file lookup times
> >>
> >> Systems with large numbers (tens of thousands and more) of network 
> >> interfaces stress the sysfs code in ways that make the linear search for 
> >> a name match take far too long.  Avoid this by using an rbtree.
> > 
> > What kind of speedups are you seeing here?  And do these changes cause a
> > memory increase due to the structure changes which outweigh the
> > speedups?
> > 
> > What kind of test are you doing to reproduce this?
> > 
> 
> Its curious because in my tests the biggest problems come from
> kernel/sysctl.c (__register_sysctl_paths) consuming 80% of cpu
> in following attempt to create 20.000 devices
> 
> (disable hotplug before trying this, and ipv6 too !)
> modprobe dummy numdummies=20000
> 
> I believe we should address __register_sysctl_paths() scalability
> problems too.

But registering 20000 devices is a far different problem from using
those 20000 devices :)

I think the "use the device" path should be the one we care the most
about fixing up, as that is much more common than the register path for
all users.

thanks,

greg k-h

^ permalink raw reply

* [PATCH] iproute2: Avoid rounding errors for 100%.
From: hannemann @ 2009-11-03 15:38 UTC (permalink / raw)
  To: shemminger; +Cc: netdev, Arnd Hannemann

From: Arnd Hannemann <hannemann@nets.rwth-aachen.de>

We noticed that a netem reorder percentage of 100% will still get packets reordered.
This patch fixes that.

Signed-off-by: Arnd Hannemann <hannemann@nets.rwth-aachen.de>
---
 tc/tc_util.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/tc/tc_util.c b/tc/tc_util.c
index fe2c7eb..2641f2e 100644
--- a/tc/tc_util.c
+++ b/tc/tc_util.c
@@ -363,8 +363,10 @@ int get_percent(__u32 *percent, const char *str)
 		return -1;
 	if (*p && strcmp(p, "%"))
 		return -1;
-
-	*percent = (unsigned) rint(per * max_percent_value);
+	if (per == 1.)
+		*percent = max_percent_value;
+	else
+		*percent = (unsigned) rint(per * max_percent_value);
 	return 0;
 }
 
-- 
1.6.3.3


^ permalink raw reply related

* Re: [PATCH] iproute2: Avoid rounding errors for 100%.
From: Arnd Hannemann @ 2009-11-03 16:19 UTC (permalink / raw)
  To: shemminger@osdl.org; +Cc: netdev@vger.kernel.org, Arnd Hannemann
In-Reply-To: <1257262694-16985-1-git-send-email-hannemann@nets.rwth-aachen.de>

Although the patch makes sense,
it does not fix the bug/effect we were seeing.
A netem reorder percentage of 100% will still get packets reordered.
(if the netem queue is not empty)


hannemann@nets.rwth-aachen.de wrote:
> From: Arnd Hannemann <hannemann@nets.rwth-aachen.de>
> 
> We noticed that a netem reorder percentage of 100% will still get packets reordered.
> This patch fixes that.
> 
> Signed-off-by: Arnd Hannemann <hannemann@nets.rwth-aachen.de>
> ---
>  tc/tc_util.c |    6 ++++--
>  1 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/tc/tc_util.c b/tc/tc_util.c
> index fe2c7eb..2641f2e 100644
> --- a/tc/tc_util.c
> +++ b/tc/tc_util.c
> @@ -363,8 +363,10 @@ int get_percent(__u32 *percent, const char *str)
>  		return -1;
>  	if (*p && strcmp(p, "%"))
>  		return -1;
> -
> -	*percent = (unsigned) rint(per * max_percent_value);
> +	if (per == 1.)
> +		*percent = max_percent_value;
> +	else
> +		*percent = (unsigned) rint(per * max_percent_value);
>  	return 0;
>  }
>  


-- 
Dipl.-Inform. Arnd Hannemann
RWTH Aachen University
Dept. of Computer Science, Informatik 4
Ahornstr. 55, D-52074 Aachen, Germany
Phone: (+49 241) 80-21423 Fax: (+49 241) 80-22220

^ permalink raw reply

* Re: [PATCH 1/3] sysfs directory scaling: rbtree for dirent name lookups
From: Octavian Purdila @ 2009-11-03 16:38 UTC (permalink / raw)
  To: Greg KH
  Cc: Eric Dumazet, Benjamin LaHaise, Eric W. Biederman, netdev,
	Cosmin Ratiu, linux-kernel
In-Reply-To: <20091103160715.GD23857@kroah.com>

On Tuesday 03 November 2009 18:07:15 you wrote:

> > > What kind of test are you doing to reproduce this?
> >
> > Its curious because in my tests the biggest problems come from
> > kernel/sysctl.c (__register_sysctl_paths) consuming 80% of cpu
> > in following attempt to create 20.000 devices
> >
> > (disable hotplug before trying this, and ipv6 too !)
> > modprobe dummy numdummies=20000
> >
> > I believe we should address __register_sysctl_paths() scalability
> > problems too.
> 
> But registering 20000 devices is a far different problem from using
> those 20000 devices :)
> 
> I think the "use the device" path should be the one we care the most
> about fixing up, as that is much more common than the register path for
> all users.
> 

For sysctl in general probably, but I would argue that for dynamic network 
interfaces (ppp and other sorts of tunnels) the "use" and "register" paths are 
not that unbalanced.

For our case where we use up to 128K interfaces, sysctl entries per network 
interface is pretty much unusable - but I agree that is not a very common case 
:) 

However [1] is not so far fetched.

[1] http://www.spinics.net/lists/netdev/msg110392.html

Thanks,
tavi

^ permalink raw reply

* Re: [PATCH 1/3] sysfs directory scaling: rbtree for dirent name lookups
From: Benjamin LaHaise @ 2009-11-03 16:45 UTC (permalink / raw)
  To: Greg KH
  Cc: Eric Dumazet, Eric W. Biederman, Octavian Purdila, netdev,
	Cosmin Ratiu, linux-kernel
In-Reply-To: <20091103160715.GD23857@kroah.com>

On Tue, Nov 03, 2009 at 08:07:15AM -0800, Greg KH wrote:
> But registering 20000 devices is a far different problem from using
> those 20000 devices :)

Registering 20,000 devices *is* a real world problem (I'm actually aiming 
for 100,000, as that's what roughly fits in a single 10Gbps link -- something 
that a mid range system can now route).  When an edge router comes up from 
reboot, or after a link has been down, the rate at which customers connect 
is important -- too slow, and you get a pile of support calls from customers 
complaining that their connection is down.  Because of the data structures 
used, there isn't even any improvement from an SMP system, so this needs 
to be addressed directly.

		-ben

^ permalink raw reply

* Re: [PATCH] iproute2: Avoid rounding errors for 100%.
From: Stephen Hemminger @ 2009-11-03 17:07 UTC (permalink / raw)
  To: Arnd Hannemann; +Cc: netdev@vger.kernel.org, Arnd Hannemann
In-Reply-To: <4AF05821.60303@nets.rwth-aachen.de>

On Tue, 03 Nov 2009 17:19:45 +0100
Arnd Hannemann <hannemann@nets.rwth-aachen.de> wrote:

> Although the patch makes sense,
> it does not fix the bug/effect we were seeing.
> A netem reorder percentage of 100% will still get packets reordered.
> (if the netem queue is not empty)
> 
> 
> hannemann@nets.rwth-aachen.de wrote:
> > From: Arnd Hannemann <hannemann@nets.rwth-aachen.de>
> > 
> > We noticed that a netem reorder percentage of 100% will still get packets reordered.
> > This patch fixes that.
> > 
> > Signed-off-by: Arnd Hannemann <hannemann@nets.rwth-aachen.de>
> > ---
> >  tc/tc_util.c |    6 ++++--
> >  1 files changed, 4 insertions(+), 2 deletions(-)
> > 
> > diff --git a/tc/tc_util.c b/tc/tc_util.c
> > index fe2c7eb..2641f2e 100644
> > --- a/tc/tc_util.c
> > +++ b/tc/tc_util.c
> > @@ -363,8 +363,10 @@ int get_percent(__u32 *percent, const char *str)
> >  		return -1;
> >  	if (*p && strcmp(p, "%"))
> >  		return -1;
> > -
> > -	*percent = (unsigned) rint(per * max_percent_value);
> > +	if (per == 1.)
> > +		*percent = max_percent_value;
> > +	else
> > +		*percent = (unsigned) rint(per * max_percent_value);
> >  	return 0;
> >  }
> >  
> 
> 

If you don't want reordering, don't specify reordering?


-- 

^ permalink raw reply

* Re: [PATCH] iproute2: Avoid rounding errors for 100%.
From: Arnd Hannemann @ 2009-11-03 17:19 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev@vger.kernel.org
In-Reply-To: <20091103090752.5b462128@nehalam>

Stephen Hemminger wrote:
> On Tue, 03 Nov 2009 17:19:45 +0100
> Arnd Hannemann <hannemann@nets.rwth-aachen.de> wrote:
> 
>> Although the patch makes sense,
>> it does not fix the bug/effect we were seeing.
>> A netem reorder percentage of 100% will still get packets reordered.
>> (if the netem queue is not empty)
>>
>>
>> hannemann@nets.rwth-aachen.de wrote:
>>> From: Arnd Hannemann <hannemann@nets.rwth-aachen.de>
>>>
>>> We noticed that a netem reorder percentage of 100% will still get packets reordered.
>>> This patch fixes that.
>>>
>>> Signed-off-by: Arnd Hannemann <hannemann@nets.rwth-aachen.de>
>>> ---
>>>  tc/tc_util.c |    6 ++++--
>>>  1 files changed, 4 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/tc/tc_util.c b/tc/tc_util.c
>>> index fe2c7eb..2641f2e 100644
>>> --- a/tc/tc_util.c
>>> +++ b/tc/tc_util.c
>>> @@ -363,8 +363,10 @@ int get_percent(__u32 *percent, const char *str)
>>>  		return -1;
>>>  	if (*p && strcmp(p, "%"))
>>>  		return -1;
>>> -
>>> -	*percent = (unsigned) rint(per * max_percent_value);
>>> +	if (per == 1.)
>>> +		*percent = max_percent_value;
>>> +	else
>>> +		*percent = (unsigned) rint(per * max_percent_value);
>>>  	return 0;
>>>  }
>>>  
>>
> 
> If you don't want reordering, don't specify reordering?

Are you arguing against the correctness of my patch?

Regarding, the reordering thingy/bug/effect whatever:
We would like to specify reordering with something like this:
Please delay 1% of the packets with 5ms.

We thought that would be possible with
tc qdisc add dev eth0 root netem delay 5m reorder 99%

But unfortunately it is not. Any better idea?

Best regards,
Arnd

^ permalink raw reply

* [PATCHv7 0/3] vhost: a kernel-level virtio server
From: Michael S. Tsirkin @ 2009-11-03 17:23 UTC (permalink / raw)
  To: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, akpm

Rusty, ok, I think I've addressed all comments so far here.  In
particular I have added write logging for live migration, indirect
buffers and virtio net header (enables gso).  I'd like this to go
into linux-next, through your tree, and hopefully 2.6.33.
What do you think?

---

This implements vhost: a kernel-level backend for virtio,
The main motivation for this work is to reduce virtualization
overhead for virtio by removing system calls on data path,
without guest changes. For virtio-net, this removes up to
4 system calls per packet: vm exit for kick, reentry for kick,
iothread wakeup for packet, interrupt injection for packet.

This driver is pretty minimal, but it's fully functional (including
migration support interfaces), and already shows performance (especially
latency) improvement over userspace.

Some more detailed description attached to the patch itself.

The patches apply to both 2.6.32-rc5 and kvm.git.  I'd like them to go
into linux-next if possible.  Please comment.

Changelog from v6:
- review comments by Daniel Walker addressed
- checkpatch cleanup
- fix build on 32 bit
- maintainers entry corrected

Changelog from v5:
- tun support
- backends with virtio net header support (enables GSO, checksum etc)
- 32 bit compat fixed
- support indirect buffers, tx exit mitigation,
  tx interrupt mitigation
- support write logging (allows migration without virtio ring code in userspace)

Changelog from v4:
- disable rx notification when have rx buffers
- addressed all comments from Rusty's review
- copy bugfixes from lguest commits:
	ebf9a5a99c1a464afe0b4dfa64416fc8b273bc5c
	e606490c440900e50ccf73a54f6fc6150ff40815

Changelog from v3:
- checkpatch fixes

Changelog from v2:
- Comments on RCU usage
- Compat ioctl support
- Make variable static
- Copied more idiomatic english from Rusty

Changes from v1:
- Move use_mm/unuse_mm from fs/aio.c to mm instead of copying.
- Reorder code to avoid need for forward declarations
- Kill a couple of debugging printks

Michael S. Tsirkin (3):
  tun: export underlying socket
  mm: export use_mm/unuse_mm to modules
  vhost_net: a kernel-level virtio server

 MAINTAINERS                |    9 +
 arch/x86/kvm/Kconfig       |    1 +
 drivers/Makefile           |    1 +
 drivers/net/tun.c          |  101 ++++-
 drivers/vhost/Kconfig      |   11 +
 drivers/vhost/Makefile     |    2 +
 drivers/vhost/net.c        |  633 +++++++++++++++++++++++++++++
 drivers/vhost/vhost.c      |  970 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/vhost/vhost.h      |  158 +++++++
 include/linux/Kbuild       |    1 +
 include/linux/if_tun.h     |   14 +
 include/linux/miscdevice.h |    1 +
 include/linux/vhost.h      |  126 ++++++
 mm/mmu_context.c           |    3 +
 14 files changed, 2012 insertions(+), 19 deletions(-)
 create mode 100644 drivers/vhost/Kconfig
 create mode 100644 drivers/vhost/Makefile
 create mode 100644 drivers/vhost/net.c
 create mode 100644 drivers/vhost/vhost.c
 create mode 100644 drivers/vhost/vhost.h
 create mode 100644 include/linux/vhost.h

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* [PATCHv7 1/3] tun: export underlying socket
From: Michael S. Tsirkin @ 2009-11-03 17:24 UTC (permalink / raw)
  To: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, akpm
In-Reply-To: <cover.1257267892.git.mst@redhat.com>

Tun device looks similar to a packet socket
in that both pass complete frames from/to userspace.

This patch fills in enough fields in the socket underlying tun driver
to support sendmsg/recvmsg operations, and message flags
MSG_TRUNC and MSG_DONTWAIT, and exports access to this socket
to modules.  Regular read/write behaviour is unchanged.

This way, code using raw sockets to inject packets
into a physical device, can support injecting
packets into host network stack almost without modification.

First user of this interface will be vhost virtualization
accelerator.

Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---

This was posted to netdev separately as well.
Assuming it's okay with davem, I think it makes sense to merge this
patch through Rusty's tree because vhost is the first user of the new
interface.  Posted here for completeness.


 drivers/net/tun.c      |  101 +++++++++++++++++++++++++++++++++++++++---------
 include/linux/if_tun.h |   14 +++++++
 2 files changed, 96 insertions(+), 19 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 4fdfa2a..18f8876 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -144,6 +144,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
 	err = 0;
 	tfile->tun = tun;
 	tun->tfile = tfile;
+	tun->socket.file = file;
 	dev_hold(tun->dev);
 	sock_hold(tun->socket.sk);
 	atomic_inc(&tfile->count);
@@ -158,6 +159,7 @@ static void __tun_detach(struct tun_struct *tun)
 	/* Detach from net device */
 	netif_tx_lock_bh(tun->dev);
 	tun->tfile = NULL;
+	tun->socket.file = NULL;
 	netif_tx_unlock_bh(tun->dev);
 
 	/* Drop read queue */
@@ -387,7 +389,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Notify and wake up reader process */
 	if (tun->flags & TUN_FASYNC)
 		kill_fasync(&tun->fasync, SIGIO, POLL_IN);
-	wake_up_interruptible(&tun->socket.wait);
+	wake_up_interruptible_poll(&tun->socket.wait, POLLIN |
+				   POLLRDNORM | POLLRDBAND);
 	return NETDEV_TX_OK;
 
 drop:
@@ -743,7 +746,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
 	len = min_t(int, skb->len, len);
 
 	skb_copy_datagram_const_iovec(skb, 0, iv, total, len);
-	total += len;
+	total += skb->len;
 
 	tun->dev->stats.tx_packets++;
 	tun->dev->stats.tx_bytes += len;
@@ -751,34 +754,23 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
 	return total;
 }
 
-static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
-			    unsigned long count, loff_t pos)
+static ssize_t tun_do_read(struct tun_struct *tun,
+			   struct kiocb *iocb, const struct iovec *iv,
+			   ssize_t len, int noblock)
 {
-	struct file *file = iocb->ki_filp;
-	struct tun_file *tfile = file->private_data;
-	struct tun_struct *tun = __tun_get(tfile);
 	DECLARE_WAITQUEUE(wait, current);
 	struct sk_buff *skb;
-	ssize_t len, ret = 0;
-
-	if (!tun)
-		return -EBADFD;
+	ssize_t ret = 0;
 
 	DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name);
 
-	len = iov_length(iv, count);
-	if (len < 0) {
-		ret = -EINVAL;
-		goto out;
-	}
-
 	add_wait_queue(&tun->socket.wait, &wait);
 	while (len) {
 		current->state = TASK_INTERRUPTIBLE;
 
 		/* Read frames from the queue */
 		if (!(skb=skb_dequeue(&tun->socket.sk->sk_receive_queue))) {
-			if (file->f_flags & O_NONBLOCK) {
+			if (noblock) {
 				ret = -EAGAIN;
 				break;
 			}
@@ -805,6 +797,27 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
 	current->state = TASK_RUNNING;
 	remove_wait_queue(&tun->socket.wait, &wait);
 
+	return ret;
+}
+
+static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
+			    unsigned long count, loff_t pos)
+{
+	struct file *file = iocb->ki_filp;
+	struct tun_file *tfile = file->private_data;
+	struct tun_struct *tun = __tun_get(tfile);
+	ssize_t len, ret;
+
+	if (!tun)
+		return -EBADFD;
+	len = iov_length(iv, count);
+	if (len < 0) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = tun_do_read(tun, iocb, iv, len, file->f_flags & O_NONBLOCK);
+	ret = min_t(ssize_t, ret, len);
 out:
 	tun_put(tun);
 	return ret;
@@ -847,7 +860,8 @@ static void tun_sock_write_space(struct sock *sk)
 		return;
 
 	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
-		wake_up_interruptible_sync(sk->sk_sleep);
+		wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT |
+						POLLWRNORM | POLLWRBAND);
 
 	tun = container_of(sk, struct tun_sock, sk)->tun;
 	kill_fasync(&tun->fasync, SIGIO, POLL_OUT);
@@ -858,6 +872,37 @@ static void tun_sock_destruct(struct sock *sk)
 	free_netdev(container_of(sk, struct tun_sock, sk)->tun->dev);
 }
 
+static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,
+		       struct msghdr *m, size_t total_len)
+{
+	struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
+	return tun_get_user(tun, m->msg_iov, total_len,
+			    m->msg_flags & MSG_DONTWAIT);
+}
+
+static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
+		       struct msghdr *m, size_t total_len,
+		       int flags)
+{
+	struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
+	int ret;
+	if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
+		return -EINVAL;
+	ret = tun_do_read(tun, iocb, m->msg_iov, total_len,
+			  flags & MSG_DONTWAIT);
+	if (ret > total_len) {
+		m->msg_flags |= MSG_TRUNC;
+		ret = flags & MSG_TRUNC ? ret : total_len;
+	}
+	return ret;
+}
+
+/* Ops structure to mimic raw sockets with tun */
+static const struct proto_ops tun_socket_ops = {
+	.sendmsg = tun_sendmsg,
+	.recvmsg = tun_recvmsg,
+};
+
 static struct proto tun_proto = {
 	.name		= "tun",
 	.owner		= THIS_MODULE,
@@ -986,6 +1031,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 			goto err_free_dev;
 
 		init_waitqueue_head(&tun->socket.wait);
+		tun->socket.ops = &tun_socket_ops;
 		sock_init_data(&tun->socket, sk);
 		sk->sk_write_space = tun_sock_write_space;
 		sk->sk_sndbuf = INT_MAX;
@@ -1489,6 +1535,23 @@ static void tun_cleanup(void)
 	rtnl_link_unregister(&tun_link_ops);
 }
 
+/* Get an underlying socket object from tun 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 *tun_get_socket(struct file *file)
+{
+	struct tun_struct *tun;
+	if (file->f_op != &tun_fops)
+		return ERR_PTR(-EINVAL);
+	tun = tun_get(file);
+	if (!tun)
+		return ERR_PTR(-EBADFD);
+	tun_put(tun);
+	return &tun->socket;
+}
+EXPORT_SYMBOL_GPL(tun_get_socket);
+
 module_init(tun_init);
 module_exit(tun_cleanup);
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h
index 3f5fd52..404abe0 100644
--- a/include/linux/if_tun.h
+++ b/include/linux/if_tun.h
@@ -86,4 +86,18 @@ struct tun_filter {
 	__u8   addr[0][ETH_ALEN];
 };
 
+#ifdef __KERNEL__
+#if defined(CONFIG_TUN) || defined(CONFIG_TUN_MODULE)
+struct socket *tun_get_socket(struct file *);
+#else
+#include <linux/err.h>
+#include <linux/errno.h>
+struct file;
+struct socket;
+static inline struct socket *tun_get_socket(struct file *f)
+{
+	return ERR_PTR(-EINVAL);
+}
+#endif /* CONFIG_TUN */
+#endif /* __KERNEL__ */
 #endif /* __IF_TUN_H */
-- 
1.6.5.2.143.g8cc62

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCHv7 2/3] mm: export use_mm/unuse_mm to modules
From: Michael S. Tsirkin @ 2009-11-03 17:24 UTC (permalink / raw)
  To: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, akpm
In-Reply-To: <cover.1257267892.git.mst@redhat.com>

vhost net module wants to do copy to/from user from a kernel thread,
which needs use_mm. Export it to modules.

Acked-by: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 mm/mmu_context.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/mm/mmu_context.c b/mm/mmu_context.c
index ded9081..0777654 100644
--- a/mm/mmu_context.c
+++ b/mm/mmu_context.c
@@ -5,6 +5,7 @@
 
 #include <linux/mm.h>
 #include <linux/mmu_context.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 
 #include <asm/mmu_context.h>
@@ -37,6 +38,7 @@ void use_mm(struct mm_struct *mm)
 	if (active_mm != mm)
 		mmdrop(active_mm);
 }
+EXPORT_SYMBOL_GPL(use_mm);
 
 /*
  * unuse_mm
@@ -56,3 +58,4 @@ void unuse_mm(struct mm_struct *mm)
 	enter_lazy_tlb(mm, tsk);
 	task_unlock(tsk);
 }
+EXPORT_SYMBOL_GPL(unuse_mm);
-- 
1.6.5.2.143.g8cc62

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* [PATCHv7 3/3] vhost_net: a kernel-level virtio server
From: Michael S. Tsirkin @ 2009-11-03 17:24 UTC (permalink / raw)
  To: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, akpm
In-Reply-To: <cover.1257267892.git.mst@redhat.com>

What it is: vhost net is a character device that can be used to reduce
the number of system calls involved in virtio networking.
Existing virtio net code is used in the guest without modification.

There's similarity with vringfd, with some differences and reduced scope
- uses eventfd for signalling
- structures can be moved around in memory at any time (good for
  migration, bug work-arounds in userspace)
- write logging is supported (good for migration)
- support memory table and not just an offset (needed for kvm)

common virtio related code has been put in a separate file vhost.c and
can be made into a separate module if/when more backends appear.  I used
Rusty's lguest.c as the source for developing this part : this supplied
me with witty comments I wouldn't be able to write myself.

What it is not: vhost net is not a bus, and not a generic new system
call. No assumptions are made on how guest performs hypercalls.
Userspace hypervisors are supported as well as kvm.

How it works: Basically, we connect virtio frontend (configured by
userspace) to a backend. The backend could be a network device, or a tap
device.  Backend is also configured by userspace, including vlan/mac
etc.

Status: This works for me, and I haven't see any crashes.
Compared to userspace, people reported improved latency (as I save up to
4 system calls per packet), as well as better bandwidth and CPU
utilization.

Features that I plan to look at in the future:
- mergeable buffers
- zero copy
- scalability tuning: figure out the best threading model to use

Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 MAINTAINERS                |    9 +
 arch/x86/kvm/Kconfig       |    1 +
 drivers/Makefile           |    1 +
 drivers/vhost/Kconfig      |   11 +
 drivers/vhost/Makefile     |    2 +
 drivers/vhost/net.c        |  633 +++++++++++++++++++++++++++++
 drivers/vhost/vhost.c      |  970 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/vhost/vhost.h      |  158 +++++++
 include/linux/Kbuild       |    1 +
 include/linux/miscdevice.h |    1 +
 include/linux/vhost.h      |  126 ++++++
 11 files changed, 1913 insertions(+), 0 deletions(-)
 create mode 100644 drivers/vhost/Kconfig
 create mode 100644 drivers/vhost/Makefile
 create mode 100644 drivers/vhost/net.c
 create mode 100644 drivers/vhost/vhost.c
 create mode 100644 drivers/vhost/vhost.h
 create mode 100644 include/linux/vhost.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8824115..980a69b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5619,6 +5619,15 @@ S:	Maintained
 F:	Documentation/filesystems/vfat.txt
 F:	fs/fat/
 
+VIRTIO HOST (VHOST)
+M:	"Michael S. Tsirkin" <mst@redhat.com>
+L:	kvm@vger.kernel.org
+L:	virtualization@lists.osdl.org
+L:	netdev@vger.kernel.org
+S:	Maintained
+F:	drivers/vhost/
+F:	include/linux/vhost.h
+
 VIA RHINE NETWORK DRIVER
 M:	Roger Luethi <rl@hellgate.ch>
 S:	Maintained
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index b84e571..94f44d9 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -64,6 +64,7 @@ config KVM_AMD
 
 # OK, it's a little counter-intuitive to do this, but it puts it neatly under
 # the virtualization menu.
+source drivers/vhost/Kconfig
 source drivers/lguest/Kconfig
 source drivers/virtio/Kconfig
 
diff --git a/drivers/Makefile b/drivers/Makefile
index 6ee53c7..81e3659 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_HID)		+= hid/
 obj-$(CONFIG_PPC_PS3)		+= ps3/
 obj-$(CONFIG_OF)		+= of/
 obj-$(CONFIG_SSB)		+= ssb/
+obj-$(CONFIG_VHOST_NET)		+= vhost/
 obj-$(CONFIG_VIRTIO)		+= virtio/
 obj-$(CONFIG_VLYNQ)		+= vlynq/
 obj-$(CONFIG_STAGING)		+= staging/
diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
new file mode 100644
index 0000000..d955406
--- /dev/null
+++ b/drivers/vhost/Kconfig
@@ -0,0 +1,11 @@
+config VHOST_NET
+	tristate "Host kernel accelerator for virtio net"
+	depends on NET && EVENTFD
+	---help---
+	  This kernel module can be loaded in host kernel to accelerate
+	  guest networking with virtio_net. Not to be confused with virtio_net
+	  module itself which needs to be loaded in guest kernel.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called vhost_net.
+
diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile
new file mode 100644
index 0000000..72dd020
--- /dev/null
+++ b/drivers/vhost/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_VHOST_NET) += vhost_net.o
+vhost_net-y := vhost.o net.o
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
new file mode 100644
index 0000000..4af3b98
--- /dev/null
+++ b/drivers/vhost/net.c
@@ -0,0 +1,633 @@
+/* Copyright (C) 2009 Red Hat, Inc.
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * virtio-net server in host kernel.
+ */
+
+#include <linux/compat.h>
+#include <linux/eventfd.h>
+#include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <linux/mmu_context.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/rcupdate.h>
+#include <linux/file.h>
+
+#include <linux/net.h>
+#include <linux/if_packet.h>
+#include <linux/if_arp.h>
+#include <linux/if_tun.h>
+
+#include <net/sock.h>
+
+#include "vhost.h"
+
+/* Max number of bytes transferred before requeueing the job.
+ * Using this limit prevents one virtqueue from starving others. */
+#define VHOST_NET_WEIGHT 0x80000
+
+enum {
+	VHOST_NET_VQ_RX = 0,
+	VHOST_NET_VQ_TX = 1,
+	VHOST_NET_VQ_MAX = 2,
+};
+
+enum vhost_net_poll_state {
+	VHOST_NET_POLL_DISABLED = 0,
+	VHOST_NET_POLL_STARTED = 1,
+	VHOST_NET_POLL_STOPPED = 2,
+};
+
+struct vhost_net {
+	struct vhost_dev dev;
+	struct vhost_virtqueue vqs[VHOST_NET_VQ_MAX];
+	struct vhost_poll poll[VHOST_NET_VQ_MAX];
+	/* Tells us whether we are polling a socket for TX.
+	 * We only do this when socket buffer fills up.
+	 * Protected by tx vq lock. */
+	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)
+{
+	if (likely(net->tx_poll_state != VHOST_NET_POLL_STARTED))
+		return;
+	vhost_poll_stop(net->poll + VHOST_NET_VQ_TX);
+	net->tx_poll_state = VHOST_NET_POLL_STOPPED;
+}
+
+/* Caller must have TX VQ lock */
+static void tx_poll_start(struct vhost_net *net, struct socket *sock)
+{
+	if (unlikely(net->tx_poll_state != VHOST_NET_POLL_STOPPED))
+		return;
+	vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file);
+	net->tx_poll_state = VHOST_NET_POLL_STARTED;
+}
+
+/* Expects to be always run from workqueue - which acts as
+ * read-size critical section for our kind of RCU. */
+static void handle_tx(struct vhost_net *net)
+{
+	struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
+	unsigned head, out, in, s;
+	struct msghdr msg = {
+		.msg_name = NULL,
+		.msg_namelen = 0,
+		.msg_control = NULL,
+		.msg_controllen = 0,
+		.msg_iov = vq->iov,
+		.msg_flags = MSG_DONTWAIT,
+	};
+	size_t len, total_len = 0;
+	int err, wmem;
+	size_t hdr_size;
+	struct socket *sock = rcu_dereference(vq->private_data);
+	if (!sock)
+		return;
+
+	wmem = atomic_read(&sock->sk->sk_wmem_alloc);
+	if (wmem >= sock->sk->sk_sndbuf)
+		return;
+
+	use_mm(net->dev.mm);
+	mutex_lock(&vq->mutex);
+	vhost_no_notify(vq);
+
+	if (wmem < sock->sk->sk_sndbuf * 2)
+		tx_poll_stop(net);
+	hdr_size = vq->hdr_size;
+
+	for (;;) {
+		head = vhost_get_vq_desc(&net->dev, vq, vq->iov, &out, &in,
+					 NULL, NULL);
+		/* Nothing new?  Wait for eventfd to tell us they refilled. */
+		if (head == vq->num) {
+			wmem = atomic_read(&sock->sk->sk_wmem_alloc);
+			if (wmem >= sock->sk->sk_sndbuf * 3 / 4) {
+				tx_poll_start(net, sock);
+				set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
+				break;
+			}
+			if (vhost_notify(vq))
+				continue;
+			break;
+		}
+		if (in) {
+			vq_err(vq, "Unexpected descriptor format for TX: "
+			       "out %d, int %d\n", out, in);
+			break;
+		}
+		/* 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);
+		/* Sanity check */
+		if (!len) {
+			vq_err(vq, "Unexpected header len for TX: "
+			       "%ld expected %zd\n",
+			       iov_length(vq->hdr, s), hdr_size);
+			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_desc(vq);
+			tx_poll_start(net, sock);
+			break;
+		}
+		if (err != len)
+			pr_err("Truncated TX packet: "
+			       " len %d != %zd\n", err, len);
+		vhost_add_used_and_trigger(&net->dev, vq, head, 0);
+		total_len += len;
+		if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
+			vhost_poll_queue(&vq->poll);
+			break;
+		}
+	}
+
+	mutex_unlock(&vq->mutex);
+	unuse_mm(net->dev.mm);
+}
+
+/* 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;
+	struct vhost_log *vq_log;
+	struct msghdr msg = {
+		.msg_name = NULL,
+		.msg_namelen = 0,
+		.msg_control = NULL, /* FIXME: get and handle RX aux data. */
+		.msg_controllen = 0,
+		.msg_iov = vq->iov,
+		.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;
+	size_t hdr_size;
+	struct socket *sock = rcu_dereference(vq->private_data);
+	if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
+		return;
+
+	use_mm(net->dev.mm);
+	mutex_lock(&vq->mutex);
+	vhost_no_notify(vq);
+	hdr_size = vq->hdr_size;
+
+	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, &out, &in,
+					 vq_log, &log);
+		/* OK, now we need to know about added descriptors. */
+		if (head == vq->num && vhost_notify(vq))
+			/* They could have slipped one in as we were doing that:
+			 * check again. */
+			continue;
+		/* Nothing new?  Wait for eventfd to tell us they refilled. */
+		if (head == vq->num)
+			break;
+		/* We don't need to be notified again. */
+		vhost_no_notify(vq);
+		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;
+		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);
+			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_desc(vq);
+			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);
+			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;
+		vhost_add_used_and_trigger(&net->dev, vq, head, len);
+		if (unlikely(vq_log))
+			vhost_log_write(vq, vq_log, log, len);
+		total_len += len;
+		if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
+			vhost_poll_queue(&vq->poll);
+			break;
+		}
+	}
+
+	mutex_unlock(&vq->mutex);
+	unuse_mm(net->dev.mm);
+}
+
+static void handle_tx_kick(struct work_struct *work)
+{
+	struct vhost_virtqueue *vq;
+	struct vhost_net *net;
+	vq = container_of(work, struct vhost_virtqueue, poll.work);
+	net = container_of(vq->dev, struct vhost_net, dev);
+	handle_tx(net);
+}
+
+static void handle_rx_kick(struct work_struct *work)
+{
+	struct vhost_virtqueue *vq;
+	struct vhost_net *net;
+	vq = container_of(work, struct vhost_virtqueue, poll.work);
+	net = container_of(vq->dev, struct vhost_net, dev);
+	handle_rx(net);
+}
+
+static void handle_tx_net(struct work_struct *work)
+{
+	struct vhost_net *net;
+	net = container_of(work, struct vhost_net, poll[VHOST_NET_VQ_TX].work);
+	handle_tx(net);
+}
+
+static void handle_rx_net(struct work_struct *work)
+{
+	struct vhost_net *net;
+	net = container_of(work, struct vhost_net, poll[VHOST_NET_VQ_RX].work);
+	handle_rx(net);
+}
+
+static int vhost_net_open(struct inode *inode, struct file *f)
+{
+	struct vhost_net *n = kzalloc(sizeof *n, GFP_KERNEL);
+	int r;
+	if (!n)
+		return -ENOMEM;
+	f->private_data = n;
+	n->vqs[VHOST_NET_VQ_TX].handle_kick = handle_tx_kick;
+	n->vqs[VHOST_NET_VQ_RX].handle_kick = handle_rx_kick;
+	r = vhost_dev_init(&n->dev, n->vqs, VHOST_NET_VQ_MAX);
+	if (r < 0) {
+		kfree(n);
+		return r;
+	}
+
+	vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, POLLOUT);
+	vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, POLLIN);
+	n->tx_poll_state = VHOST_NET_POLL_DISABLED;
+	return 0;
+}
+
+static void vhost_net_disable_vq(struct vhost_net *n, int index)
+{
+	if (!n->vqs[index].private_data)
+		return;
+	if (index == VHOST_NET_VQ_TX) {
+		tx_poll_stop(n);
+		n->tx_poll_state = VHOST_NET_POLL_DISABLED;
+	} else
+		vhost_poll_stop(n->poll + VHOST_NET_VQ_RX);
+}
+
+static void vhost_net_enable_vq(struct vhost_net *n, int index)
+{
+	struct socket *sock = n->vqs[index].private_data;
+	if (!sock)
+		return;
+	if (index == VHOST_NET_VQ_TX) {
+		n->tx_poll_state = VHOST_NET_POLL_STOPPED;
+		tx_poll_start(n, sock);
+	} else
+		vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file);
+}
+
+static struct socket *vhost_net_stop_vq(struct vhost_net *n, int index)
+{
+	struct socket *sock;
+
+	mutex_lock(&n->vqs[index].mutex);
+	sock = n->vqs[index].private_data;
+	vhost_net_disable_vq(n, index);
+	rcu_assign_pointer(n->vqs[index].private_data, NULL);
+	mutex_unlock(&n->vqs[index].mutex);
+	return sock;
+}
+
+static void vhost_net_stop(struct vhost_net *n, struct socket **tx_sock,
+			   struct socket **rx_sock)
+{
+	*tx_sock = vhost_net_stop_vq(n, VHOST_NET_VQ_TX);
+	*rx_sock = vhost_net_stop_vq(n, VHOST_NET_VQ_RX);
+}
+
+static void vhost_net_flush_vq(struct vhost_net *n, int index)
+{
+	vhost_poll_flush(n->poll + index);
+	vhost_poll_flush(&n->dev.vqs[index].poll);
+}
+
+static void vhost_net_flush(struct vhost_net *n)
+{
+	vhost_net_flush_vq(n, VHOST_NET_VQ_TX);
+	vhost_net_flush_vq(n, VHOST_NET_VQ_RX);
+}
+
+static int vhost_net_release(struct inode *inode, struct file *f)
+{
+	struct vhost_net *n = f->private_data;
+	struct socket *tx_sock;
+	struct socket *rx_sock;
+
+	vhost_net_stop(n, &tx_sock, &rx_sock);
+	vhost_net_flush(n);
+	vhost_dev_cleanup(&n->dev);
+	if (tx_sock)
+		fput(tx_sock->file);
+	if (rx_sock)
+		fput(rx_sock->file);
+	/* We do an extra flush before freeing memory,
+	 * since jobs can re-queue themselves. */
+	vhost_net_flush(n);
+	kfree(n);
+	return 0;
+}
+
+static struct socket *get_raw_socket(int fd)
+{
+	struct {
+		struct sockaddr_ll sa;
+		char  buf[MAX_ADDR_LEN];
+	} uaddr;
+	int uaddr_len = sizeof uaddr, r;
+	struct socket *sock = sockfd_lookup(fd, &r);
+	if (!sock)
+		return ERR_PTR(-ENOTSOCK);
+
+	/* Parameter checking */
+	if (sock->sk->sk_type != SOCK_RAW) {
+		r = -ESOCKTNOSUPPORT;
+		goto err;
+	}
+
+	r = sock->ops->getname(sock, (struct sockaddr *)&uaddr.sa,
+			       &uaddr_len, 0);
+	if (r)
+		goto err;
+
+	if (uaddr.sa.sll_family != AF_PACKET) {
+		r = -EPFNOSUPPORT;
+		goto err;
+	}
+	return sock;
+err:
+	fput(sock->file);
+	return ERR_PTR(r);
+}
+
+static struct socket *get_tun_socket(int fd)
+{
+	struct file *file = fget(fd);
+	struct socket *sock;
+	if (!file)
+		return ERR_PTR(-EBADF);
+	sock = tun_get_socket(file);
+	if (IS_ERR(sock))
+		fput(file);
+	return sock;
+}
+
+static struct socket *get_socket(int fd)
+{
+	struct socket *sock;
+	if (fd == -1)
+		return NULL;
+	sock = get_raw_socket(fd);
+	if (!IS_ERR(sock))
+		return sock;
+	sock = get_tun_socket(fd);
+	if (!IS_ERR(sock))
+		return sock;
+	return ERR_PTR(-ENOTSOCK);
+}
+
+static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
+{
+	struct socket *sock, *oldsock = NULL;
+	struct vhost_virtqueue *vq;
+	int r;
+
+	mutex_lock(&n->dev.mutex);
+	r = vhost_dev_check_owner(&n->dev);
+	if (r)
+		goto done;
+
+	if (index >= VHOST_NET_VQ_MAX) {
+		r = -ENOBUFS;
+		goto done;
+	}
+	vq = n->vqs + index;
+	mutex_lock(&vq->mutex);
+	sock = get_socket(fd);
+	if (IS_ERR(sock)) {
+		r = PTR_ERR(sock);
+		goto done;
+	}
+
+	/* start polling new socket */
+	oldsock = vq->private_data;
+	if (sock == oldsock)
+		goto done;
+
+	vhost_net_disable_vq(n, index);
+	rcu_assign_pointer(vq->private_data, sock);
+	vhost_net_enable_vq(n, index);
+	mutex_unlock(&vq->mutex);
+done:
+	mutex_unlock(&n->dev.mutex);
+	if (oldsock) {
+		vhost_net_flush_vq(n, index);
+		fput(oldsock->file);
+	}
+	return r;
+}
+
+static long vhost_net_reset_owner(struct vhost_net *n)
+{
+	struct socket *tx_sock = NULL;
+	struct socket *rx_sock = NULL;
+	long r;
+	mutex_lock(&n->dev.mutex);
+	r = vhost_dev_check_owner(&n->dev);
+	if (r)
+		goto done;
+	vhost_net_stop(n, &tx_sock, &rx_sock);
+	vhost_net_flush(n);
+	r = vhost_dev_reset_owner(&n->dev);
+done:
+	mutex_unlock(&n->dev.mutex);
+	if (tx_sock)
+		fput(tx_sock->file);
+	if (rx_sock)
+		fput(rx_sock->file);
+	return r;
+}
+
+static void 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_unlock(&n->dev.mutex);
+	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;
+		mutex_unlock(&n->vqs[i].mutex);
+	}
+	mutex_unlock(&n->dev.mutex);
+	vhost_net_flush(n);
+}
+
+static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
+			    unsigned long arg)
+{
+	struct vhost_net *n = f->private_data;
+	void __user *argp = (void __user *)arg;
+	u32 __user *featurep = argp;
+	struct vhost_vring_file backend;
+	u64 features;
+	int r;
+	switch (ioctl) {
+	case VHOST_NET_SET_BACKEND:
+		r = copy_from_user(&backend, argp, sizeof backend);
+		if (r < 0)
+			return r;
+		return vhost_net_set_backend(n, backend.index, backend.fd);
+	case VHOST_GET_FEATURES:
+		features = VHOST_FEATURES;
+		return put_user(features, featurep);
+	case VHOST_ACK_FEATURES:
+		r = get_user(features, featurep);
+		/* No features for now */
+		if (r < 0)
+			return r;
+		if (features & ~VHOST_FEATURES)
+			return -EOPNOTSUPP;
+		vhost_net_set_features(n, features);
+		return 0;
+	case VHOST_RESET_OWNER:
+		return vhost_net_reset_owner(n);
+	default:
+		r = vhost_dev_ioctl(&n->dev, ioctl, arg);
+		vhost_net_flush(n);
+		return r;
+	}
+}
+
+#ifdef CONFIG_COMPAT
+static long vhost_net_compat_ioctl(struct file *f, unsigned int ioctl,
+				   unsigned long arg)
+{
+	return vhost_net_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+const static struct file_operations vhost_net_fops = {
+	.owner          = THIS_MODULE,
+	.release        = vhost_net_release,
+	.unlocked_ioctl = vhost_net_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = vhost_net_compat_ioctl,
+#endif
+	.open           = vhost_net_open,
+};
+
+static struct miscdevice vhost_net_misc = {
+	VHOST_NET_MINOR,
+	"vhost-net",
+	&vhost_net_fops,
+};
+
+int vhost_net_init(void)
+{
+	int r = vhost_init();
+	if (r)
+		goto err_init;
+	r = misc_register(&vhost_net_misc);
+	if (r)
+		goto err_reg;
+	return 0;
+err_reg:
+	vhost_cleanup();
+err_init:
+	return r;
+
+}
+module_init(vhost_net_init);
+
+void vhost_net_exit(void)
+{
+	misc_deregister(&vhost_net_misc);
+	vhost_cleanup();
+}
+module_exit(vhost_net_exit);
+
+MODULE_VERSION("0.0.1");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Michael S. Tsirkin");
+MODULE_DESCRIPTION("Host kernel accelerator for virtio net");
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
new file mode 100644
index 0000000..9e2ecc3
--- /dev/null
+++ b/drivers/vhost/vhost.c
@@ -0,0 +1,970 @@
+/* Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2006 Rusty Russell IBM Corporation
+ *
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * Inspiration, some code, and most witty comments come from
+ * Documentation/lguest/lguest.c, by Rusty Russell
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * Generic code for virtio server in host kernel.
+ */
+
+#include <linux/eventfd.h>
+#include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/rcupdate.h>
+#include <linux/poll.h>
+#include <linux/file.h>
+#include <linux/highmem.h>
+
+#include <linux/net.h>
+#include <linux/if_packet.h>
+#include <linux/if_arp.h>
+
+#include <net/sock.h>
+
+#include "vhost.h"
+
+enum {
+	VHOST_MEMORY_MAX_NREGIONS = 64,
+	VHOST_MEMORY_F_LOG = 0x1,
+};
+
+static struct workqueue_struct *vhost_workqueue;
+
+static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
+			    poll_table *pt)
+{
+	struct vhost_poll *poll;
+	poll = container_of(pt, struct vhost_poll, table);
+
+	poll->wqh = wqh;
+	add_wait_queue(wqh, &poll->wait);
+}
+
+static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync,
+			     void *key)
+{
+	struct vhost_poll *poll;
+	poll = container_of(wait, struct vhost_poll, wait);
+	if (!((unsigned long)key & poll->mask))
+		return 0;
+
+	queue_work(vhost_workqueue, &poll->work);
+	return 0;
+}
+
+/* Init poll structure */
+void vhost_poll_init(struct vhost_poll *poll, work_func_t func,
+		     unsigned long mask)
+{
+	INIT_WORK(&poll->work, func);
+	init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup);
+	init_poll_funcptr(&poll->table, vhost_poll_func);
+	poll->mask = mask;
+}
+
+/* Start polling a file. We add ourselves to file's wait queue. The caller must
+ * keep a reference to a file until after vhost_poll_stop is called. */
+void vhost_poll_start(struct vhost_poll *poll, struct file *file)
+{
+	unsigned long mask;
+	mask = file->f_op->poll(file, &poll->table);
+	if (mask)
+		vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask);
+}
+
+/* Stop polling a file. After this function returns, it becomes safe to drop the
+ * file reference. You must also flush afterwards. */
+void vhost_poll_stop(struct vhost_poll *poll)
+{
+	remove_wait_queue(poll->wqh, &poll->wait);
+}
+
+/* Flush any work that has been scheduled. When calling this, don't hold any
+ * locks that are also used by the callback. */
+void vhost_poll_flush(struct vhost_poll *poll)
+{
+	flush_work(&poll->work);
+}
+
+void vhost_poll_queue(struct vhost_poll *poll)
+{
+	queue_work(vhost_workqueue, &poll->work);
+}
+
+long vhost_dev_init(struct vhost_dev *dev,
+		    struct vhost_virtqueue *vqs, int nvqs)
+{
+	int i;
+	dev->vqs = vqs;
+	dev->nvqs = nvqs;
+	mutex_init(&dev->mutex);
+
+	for (i = 0; i < dev->nvqs; ++i) {
+		dev->vqs[i].dev = dev;
+		mutex_init(&dev->vqs[i].mutex);
+		if (dev->vqs[i].handle_kick)
+			vhost_poll_init(&dev->vqs[i].poll,
+					dev->vqs[i].handle_kick,
+					POLLIN);
+	}
+	return 0;
+}
+
+/* Caller should have device mutex */
+long vhost_dev_check_owner(struct vhost_dev *dev)
+{
+	/* Are you the owner? If not, I don't think you mean to do that */
+	return dev->mm == current->mm ? 0 : -EPERM;
+}
+
+/* Caller should have device mutex */
+static long vhost_dev_set_owner(struct vhost_dev *dev)
+{
+	/* Is there an owner already? */
+	if (dev->mm)
+		return -EBUSY;
+	/* No owner, become one */
+	dev->mm = get_task_mm(current);
+	return 0;
+}
+
+/* Caller should have device mutex */
+long vhost_dev_reset_owner(struct vhost_dev *dev)
+{
+	struct vhost_memory *memory;
+
+	/* Restore memory to default 1:1 mapping. */
+	memory = kzalloc(offsetof(struct vhost_memory, regions) +
+			 2 * sizeof *memory->regions, GFP_KERNEL);
+	if (!memory)
+		return -ENOMEM;
+
+	vhost_dev_cleanup(dev);
+
+	memory->nregions = 2;
+	memory->regions[0].guest_phys_addr = 1;
+	memory->regions[0].userspace_addr = 1;
+	memory->regions[0].memory_size = ~0ULL;
+	memory->regions[1].guest_phys_addr = 0;
+	memory->regions[1].userspace_addr = 0;
+	memory->regions[1].memory_size = 1;
+	dev->memory = memory;
+	return 0;
+}
+
+/* Caller should have device mutex */
+void vhost_dev_cleanup(struct vhost_dev *dev)
+{
+	int i;
+	for (i = 0; i < dev->nvqs; ++i) {
+		if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
+			vhost_poll_stop(&dev->vqs[i].poll);
+			vhost_poll_flush(&dev->vqs[i].poll);
+		}
+		if (dev->vqs[i].error_ctx)
+			eventfd_ctx_put(dev->vqs[i].error_ctx);
+		if (dev->vqs[i].error)
+			fput(dev->vqs[i].error);
+		if (dev->vqs[i].kick)
+			fput(dev->vqs[i].kick);
+		if (dev->vqs[i].call_ctx)
+			eventfd_ctx_put(dev->vqs[i].call_ctx);
+		if (dev->vqs[i].call)
+			fput(dev->vqs[i].call);
+		dev->vqs[i].error_ctx = NULL;
+		dev->vqs[i].error = NULL;
+		dev->vqs[i].kick = NULL;
+		dev->vqs[i].call_ctx = NULL;
+		dev->vqs[i].call = NULL;
+	}
+	if (dev->log_ctx)
+		eventfd_ctx_put(dev->log_ctx);
+	dev->log_ctx = NULL;
+	if (dev->log_file)
+		fput(dev->log_file);
+	dev->log_file = NULL;
+	/* No one will access memory at this point */
+	kfree(dev->memory);
+	dev->memory = NULL;
+	if (dev->mm)
+		mmput(dev->mm);
+	dev->mm = NULL;
+}
+
+static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
+{
+	struct vhost_memory mem, *newmem, *oldmem;
+	unsigned long size = offsetof(struct vhost_memory, regions);
+	long r;
+	r = copy_from_user(&mem, m, size);
+	if (r)
+		return r;
+	if (mem.padding)
+		return -EOPNOTSUPP;
+	if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS)
+		return -E2BIG;
+	newmem = kmalloc(size + mem.nregions * sizeof *m->regions, GFP_KERNEL);
+	if (!newmem)
+		return -ENOMEM;
+
+	memcpy(newmem, &mem, size);
+	r = copy_from_user(newmem->regions, m->regions,
+			   mem.nregions * sizeof *m->regions);
+	if (r) {
+		kfree(newmem);
+		return r;
+	}
+	oldmem = d->memory;
+	rcu_assign_pointer(d->memory, newmem);
+	synchronize_rcu();
+	kfree(oldmem);
+	return 0;
+}
+
+static int init_used(struct vhost_virtqueue *vq)
+{
+	int r = put_user(vq->used_flags, &vq->used->flags);
+	if (r)
+		return r;
+	return get_user(vq->last_used_idx, &vq->used->idx);
+}
+
+static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
+{
+	struct file *eventfp, *filep = NULL,
+		    *pollstart = NULL, *pollstop = NULL;
+	struct eventfd_ctx *ctx = NULL;
+	u32 __user *idxp = argp;
+	struct vhost_virtqueue *vq;
+	struct vhost_vring_state s;
+	struct vhost_vring_file f;
+	struct vhost_vring_addr a;
+	u32 idx;
+	long r;
+
+	r = get_user(idx, idxp);
+	if (r < 0)
+		return r;
+	if (idx > d->nvqs)
+		return -ENOBUFS;
+
+	vq = d->vqs + idx;
+
+	mutex_lock(&vq->mutex);
+
+	switch (ioctl) {
+	case VHOST_SET_VRING_NUM:
+		r = copy_from_user(&s, argp, sizeof s);
+		if (r < 0)
+			break;
+		if (s.num > 0xffff) {
+			r = -EINVAL;
+			break;
+		}
+		vq->num = s.num;
+		break;
+	case VHOST_SET_VRING_BASE:
+		r = copy_from_user(&s, argp, sizeof s);
+		if (r < 0)
+			break;
+		if (s.num > 0xffff) {
+			r = -EINVAL;
+			break;
+		}
+		vq->avail_idx = vq->last_avail_idx = s.num;
+		break;
+	case VHOST_GET_VRING_BASE:
+		s.index = idx;
+		s.num = vq->last_avail_idx;
+		r = copy_to_user(argp, &s, sizeof s);
+		break;
+	case VHOST_SET_VRING_DESC:
+		r = copy_from_user(&a, argp, sizeof a);
+		if (r < 0)
+			break;
+		if (a.padding) {
+			r = -EOPNOTSUPP;
+			break;
+		}
+		if ((u64)(unsigned long)a.user_addr != a.user_addr) {
+			r = -EFAULT;
+			break;
+		}
+		vq->desc = (void __user *)(unsigned long)a.user_addr;
+		break;
+	case VHOST_SET_VRING_AVAIL:
+		r = copy_from_user(&a, argp, sizeof a);
+		if (r < 0)
+			break;
+		if (a.padding) {
+			r = -EOPNOTSUPP;
+			break;
+		}
+		if ((u64)(unsigned long)a.user_addr != a.user_addr) {
+			r = -EFAULT;
+			break;
+		}
+		if (a.user_addr & (sizeof *vq->avail->ring - 1)) {
+			r = -EINVAL;
+			break;
+		}
+		vq->avail = (void __user *)(unsigned long)a.user_addr;
+		/* Forget the cached index value. */
+		vq->avail_idx = vq->last_avail_idx;
+		break;
+	case VHOST_SET_VRING_USED:
+		r = copy_from_user(&a, argp, sizeof a);
+		if (r < 0)
+			break;
+		if (a.padding) {
+			r = -EOPNOTSUPP;
+			break;
+		}
+		if ((u64)(unsigned long)a.user_addr != a.user_addr) {
+			r = -EFAULT;
+			break;
+		}
+		if (a.user_addr & (sizeof *vq->used->ring - 1)) {
+			r = -EINVAL;
+			break;
+		}
+		vq->used = (void __user *)(unsigned long)a.user_addr;
+		r = init_used(vq);
+		if (r)
+			break;
+		break;
+	case VHOST_SET_VRING_LOG:
+		r = copy_from_user(&a, argp, sizeof a);
+		if (r < 0)
+			break;
+		if (a.padding) {
+			r = -EOPNOTSUPP;
+			break;
+		}
+		if (a.user_addr == VHOST_VRING_LOG_DISABLE) {
+			vq->log_used = false;
+			break;
+		}
+		if (a.user_addr & (sizeof *vq->used->ring - 1)) {
+			r = -EINVAL;
+			break;
+		}
+		vq->log_used = true;
+		vq->log_addr = a.user_addr;
+		break;
+	case VHOST_SET_VRING_KICK:
+		r = copy_from_user(&f, argp, sizeof f);
+		if (r < 0)
+			break;
+		eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
+		if (IS_ERR(eventfp))
+			return PTR_ERR(eventfp);
+		if (eventfp != vq->kick) {
+			pollstop = filep = vq->kick;
+			pollstart = vq->kick = eventfp;
+		} else
+			filep = eventfp;
+		break;
+	case VHOST_SET_VRING_CALL:
+		r = copy_from_user(&f, argp, sizeof f);
+		if (r < 0)
+			break;
+		eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
+		if (IS_ERR(eventfp))
+			return PTR_ERR(eventfp);
+		if (eventfp != vq->call) {
+			filep = vq->call;
+			ctx = vq->call_ctx;
+			vq->call = eventfp;
+			vq->call_ctx = eventfp ?
+				eventfd_ctx_fileget(eventfp) : NULL;
+		} else
+			filep = eventfp;
+		break;
+	case VHOST_SET_VRING_ERR:
+		r = copy_from_user(&f, argp, sizeof f);
+		if (r < 0)
+			break;
+		eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd);
+		if (IS_ERR(eventfp))
+			return PTR_ERR(eventfp);
+		if (eventfp != vq->error) {
+			filep = vq->error;
+			vq->error = eventfp;
+			ctx = vq->error_ctx;
+			vq->error_ctx = eventfp ?
+				eventfd_ctx_fileget(eventfp) : NULL;
+		} else
+			filep = eventfp;
+		break;
+	default:
+		r = -ENOIOCTLCMD;
+	}
+
+	if (pollstop && vq->handle_kick)
+		vhost_poll_stop(&vq->poll);
+
+	if (ctx)
+		eventfd_ctx_put(ctx);
+	if (filep)
+		fput(filep);
+
+	if (pollstart && vq->handle_kick)
+		vhost_poll_start(&vq->poll, vq->kick);
+
+	mutex_unlock(&vq->mutex);
+
+	if (pollstop && vq->handle_kick)
+		vhost_poll_flush(&vq->poll);
+	return r;
+}
+
+long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	struct file *eventfp, *filep = NULL;
+	struct eventfd_ctx *ctx = NULL;
+	u64 p;
+	long r;
+	int i, fd;
+
+	mutex_lock(&d->mutex);
+	/* If you are not the owner, you can become one */
+	if (ioctl == VHOST_SET_OWNER) {
+		r = vhost_dev_set_owner(d);
+		goto done;
+	}
+
+	/* You must be the owner to do anything else */
+	r = vhost_dev_check_owner(d);
+	if (r)
+		goto done;
+
+	switch (ioctl) {
+	case VHOST_SET_MEM_TABLE:
+		r = vhost_set_memory(d, argp);
+		break;
+	case VHOST_SET_LOG_BASE:
+		r = get_user(p, (u64 __user *)argp);
+		if (r < 0)
+			break;
+		if ((u64)(unsigned long)p != p) {
+			r = -EFAULT;
+			break;
+		}
+		for (i = 0; i < d->nvqs; ++i) {
+			mutex_lock(&d->vqs[i].mutex);
+			d->vqs[i].log_base = (void __user *)(unsigned long)p;
+			mutex_unlock(&d->vqs[i].mutex);
+		}
+		break;
+	case VHOST_SET_LOG_FD:
+		r = get_user(fd, (int __user *)argp);
+		if (r < 0)
+			break;
+		eventfp = fd == -1 ? NULL : eventfd_fget(fd);
+		if (IS_ERR(eventfp)) {
+			r = PTR_ERR(eventfp);
+			break;
+		}
+		if (eventfp != d->log_file) {
+			filep = d->log_file;
+			ctx = d->log_ctx;
+			d->log_ctx = eventfp ?
+				eventfd_ctx_fileget(eventfp) : NULL;
+		} else
+			filep = eventfp;
+		for (i = 0; i < d->nvqs; ++i) {
+			mutex_lock(&d->vqs[i].mutex);
+			d->vqs[i].log_ctx = d->log_ctx;
+			mutex_unlock(&d->vqs[i].mutex);
+		}
+		if (ctx)
+			eventfd_ctx_put(ctx);
+		if (filep)
+			fput(filep);
+		break;
+	default:
+		r = vhost_set_vring(d, ioctl, argp);
+		break;
+	}
+done:
+	mutex_unlock(&d->mutex);
+	return r;
+}
+
+static const struct vhost_memory_region *find_region(struct vhost_memory *mem,
+						     __u64 addr, __u32 len)
+{
+	struct vhost_memory_region *reg;
+	int i;
+	/* linear search is not brilliant, but we really have on the order of 6
+	 * regions in practice */
+	for (i = 0; i < mem->nregions; ++i) {
+		reg = mem->regions + i;
+		if (reg->guest_phys_addr <= addr &&
+		    reg->guest_phys_addr + reg->memory_size - 1 >= addr)
+			return reg;
+	}
+	return NULL;
+}
+
+/* TODO: This is really inefficient.  We need something like get_user()
+ * (instruction directly accesses the data, with an exception table entry
+ * returning -EFAULT). See Documentation/x86/exception-tables.txt.
+ */
+static int set_bit_to_user(int nr, void __user *addr)
+{
+	unsigned long log = (unsigned long)addr;
+	struct page *page;
+	void *base;
+	int bit = nr + (log % PAGE_SIZE) * 8;
+	int r;
+	r = get_user_pages_fast(log, 1, 1, &page);
+	if (r)
+		return r;
+	base = kmap_atomic(page, KM_USER0);
+	set_bit(bit, base);
+	kunmap_atomic(base, KM_USER0);
+	set_page_dirty_lock(page);
+	put_page(page);
+	return 0;
+}
+
+static int log_write(void __user *log_base,
+		     u64 write_address, u64 write_length)
+{
+	int r;
+	if (!write_length)
+		return 0;
+	write_address /= VHOST_PAGE_SIZE;
+	for (;;) {
+		u64 base = (u64)log_base;
+		u64 log = base + write_address / 8;
+		int bit = write_address % 8;
+		if ((u64)(unsigned long)log != log)
+			return -EFAULT;
+		r = set_bit_to_user(bit, (void __user *)log);
+		if (r < 0)
+			return r;
+		if (write_length <= VHOST_PAGE_SIZE)
+			break;
+		write_length -= VHOST_PAGE_SIZE;
+		write_address += VHOST_PAGE_SIZE;
+	}
+	return r;
+}
+
+int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
+		    unsigned int log_num, u64 len)
+{
+	int i, r;
+
+	/* Make sure data written is seen before log. */
+	wmb();
+	for (i = 0; i < log_num; ++i) {
+		u64 l = min(log[i].len, len);
+		r = log_write(vq->log_base, log[i].addr, l);
+		if (r < 0)
+			return r;
+		len -= l;
+		if (!len)
+			return 0;
+	}
+	if (vq->log_ctx)
+		eventfd_signal(vq->log_ctx, 1);
+	/* Length written exceeds what we have stored. This is a bug. */
+	BUG();
+	return 0;
+}
+
+int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
+		   struct iovec iov[], int iov_size)
+{
+	const struct vhost_memory_region *reg;
+	struct vhost_memory *mem;
+	struct iovec *_iov;
+	u64 s = 0;
+	int ret = 0;
+
+	rcu_read_lock();
+
+	mem = rcu_dereference(dev->memory);
+	while ((u64)len > s) {
+		u64 size;
+		if (ret >= iov_size) {
+			ret = -ENOBUFS;
+			break;
+		}
+		reg = find_region(mem, addr, len);
+		if (!reg) {
+			ret = -EFAULT;
+			break;
+		}
+		_iov = iov + ret;
+		size = reg->memory_size - addr + reg->guest_phys_addr;
+		_iov->iov_len = min((u64)len, size);
+		_iov->iov_base = (void *)
+			(reg->userspace_addr + addr - reg->guest_phys_addr);
+		s += size;
+		addr += size;
+		++ret;
+	}
+
+	rcu_read_unlock();
+	return ret;
+}
+
+/* Each buffer in the virtqueues is actually a chain of descriptors.  This
+ * function returns the next descriptor in the chain,
+ * or -1 if we're at the end. */
+static unsigned next_desc(struct vring_desc *desc)
+{
+	unsigned int next;
+
+	/* If this descriptor says it doesn't chain, we're done. */
+	if (!(desc->flags & VRING_DESC_F_NEXT))
+		return -1;
+
+	/* Check they're not leading us off end of descriptors. */
+	next = desc->next;
+	/* Make sure compiler knows to grab that: we don't want it changing! */
+	/* We will use the result as an index in an array, so most
+	 * architectures only need a compiler barrier here. */
+	read_barrier_depends();
+
+	return next;
+}
+
+static unsigned get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
+			     struct iovec iov[],
+			     unsigned int *out_num, unsigned int *in_num,
+			     struct vhost_log *log, unsigned int *log_num,
+			     struct vring_desc *indirect)
+{
+	struct vring_desc desc;
+	unsigned int i = 0, count, found = 0;
+	int ret;
+
+	/* Sanity check */
+	if (indirect->len % sizeof desc) {
+		vq_err(vq, "Invalid length in indirect descriptor: "
+		       "len 0x%llx not multiple of 0x%zx\n",
+		       (unsigned long long)indirect->len,
+		       sizeof desc);
+		return -EINVAL;
+	}
+
+	ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect,
+			     ARRAY_SIZE(vq->indirect));
+	if (ret < 0) {
+		vq_err(vq, "Translation failure %d in indirect.\n", ret);
+		return ret;
+	}
+
+	/* We will use the result as an address to read from, so most
+	 * architectures only need a compiler barrier here. */
+	read_barrier_depends();
+
+	count = indirect->len / sizeof desc;
+	/* Buffers are chained via a 16 bit next field, so
+	 * we can have at most 2^16 of these. */
+	if (count > USHORT_MAX + 1) {
+		vq_err(vq, "Indirect buffer length too big: %d\n",
+		       indirect->len);
+		return -E2BIG;
+	}
+
+	do {
+		unsigned iov_count = *in_num + *out_num;
+		if (++found > count) {
+			vq_err(vq, "Loop detected: last one at %u "
+			       "indirect size %u\n",
+			       i, count);
+			return -EINVAL;
+		}
+		if (memcpy_fromiovec((unsigned char *)&desc, vq->indirect,
+				     sizeof desc)) {
+			vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n",
+			       i, (size_t)indirect->addr + i * sizeof desc);
+			return -EINVAL;
+		}
+		if (desc.flags & VRING_DESC_F_INDIRECT) {
+			vq_err(vq, "Nested indirect descriptor: idx %d, %zx\n",
+			       i, (size_t)indirect->addr + i * sizeof desc);
+			return -EINVAL;
+		}
+
+		ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,
+				     VHOST_NET_MAX_SG - iov_count);
+		if (ret < 0) {
+			vq_err(vq, "Translation failure %d indirect idx %d\n",
+			       ret, i);
+			return ret;
+		}
+		/* If this is an input descriptor, increment that count. */
+		if (desc.flags & VRING_DESC_F_WRITE) {
+			*in_num += ret;
+			if (unlikely(log)) {
+				log[*log_num].addr = desc.addr;
+				log[*log_num].len = desc.len;
+				++*log_num;
+			}
+		} else {
+			/* If it's an output descriptor, they're all supposed
+			 * to come before any input descriptors. */
+			if (*in_num) {
+				vq_err(vq, "Indirect descriptor "
+				       "has out after in: idx %d\n", i);
+				return -EINVAL;
+			}
+			*out_num += ret;
+		}
+	} while ((i = next_desc(&desc)) != -1);
+	return 0;
+}
+
+/* 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
+ * iovecs, but we pack them into one and note how many of each there were.
+ *
+ * This function returns the descriptor number found, or vq->num (which
+ * is never a valid descriptor number) if none was found. */
+unsigned vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
+			   struct iovec iov[],
+			   unsigned int *out_num, unsigned int *in_num,
+			   struct vhost_log *log, unsigned int *log_num)
+{
+	struct vring_desc desc;
+	unsigned int i, head, found = 0;
+	u16 last_avail_idx;
+	int ret;
+
+	/* Check it isn't doing very strange things with descriptor numbers. */
+	last_avail_idx = vq->last_avail_idx;
+	if (get_user(vq->avail_idx, &vq->avail->idx)) {
+		vq_err(vq, "Failed to access avail idx at %p\n",
+		       &vq->avail->idx);
+		return vq->num;
+	}
+
+	if ((u16)(vq->avail_idx - last_avail_idx) > vq->num) {
+		vq_err(vq, "Guest moved used index from %u to %u",
+		       last_avail_idx, vq->avail_idx);
+		return vq->num;
+	}
+
+	/* If there's nothing new since last we looked, return invalid. */
+	if (vq->avail_idx == last_avail_idx)
+		return vq->num;
+
+	/* Only get avail ring entries after they have been exposed by guest. */
+	rmb();
+
+	/* Grab the next descriptor number they're advertising, and increment
+	 * the index we've seen. */
+	if (get_user(head, &vq->avail->ring[last_avail_idx % vq->num])) {
+		vq_err(vq, "Failed to read head: idx %d address %p\n",
+		       last_avail_idx,
+		       &vq->avail->ring[last_avail_idx % vq->num]);
+		return vq->num;
+	}
+
+	/* If their number is silly, that's an error. */
+	if (head >= vq->num) {
+		vq_err(vq, "Guest says index %u > %u is available",
+		       head, vq->num);
+		return vq->num;
+	}
+
+	/* When we start there are none of either input nor output. */
+	*out_num = *in_num = 0;
+	if (unlikely(log))
+		*log_num = 0;
+
+	i = head;
+	do {
+		unsigned iov_count = *in_num + *out_num;
+		if (i >= vq->num) {
+			vq_err(vq, "Desc index is %u > %u, head = %u",
+			       i, vq->num, head);
+			return vq->num;
+		}
+		if (++found > vq->num) {
+			vq_err(vq, "Loop detected: last one at %u "
+			       "vq size %u head %u\n",
+			       i, vq->num, head);
+			return vq->num;
+		}
+		ret = copy_from_user(&desc, vq->desc + i, sizeof desc);
+		if (ret) {
+			vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
+			       i, vq->desc + i);
+			return vq->num;
+		}
+		if (desc.flags & VRING_DESC_F_INDIRECT) {
+			ret = get_indirect(dev, vq, iov, out_num, in_num,
+					   log, log_num, &desc);
+			if (ret < 0) {
+				vq_err(vq, "Failure detected "
+				       "in indirect descriptor at idx %d\n", i);
+				return vq->num;
+			}
+			continue;
+		}
+
+		ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count,
+				     VHOST_NET_MAX_SG - iov_count);
+		if (ret < 0) {
+			vq_err(vq, "Translation failure %d descriptor idx %d\n",
+			       ret, i);
+			return vq->num;
+		}
+		if (desc.flags & VRING_DESC_F_WRITE) {
+			/* If this is an input descriptor,
+			 * increment that count. */
+			*in_num += ret;
+			if (unlikely(log)) {
+				log[*log_num].addr = desc.addr;
+				log[*log_num].len = desc.len;
+				++*log_num;
+			}
+		} else {
+			/* If it's an output descriptor, they're all supposed
+			 * to come before any input descriptors. */
+			if (*in_num) {
+				vq_err(vq, "Descriptor has out after in: "
+				       "idx %d\n", i);
+				return vq->num;
+			}
+			*out_num += ret;
+		}
+	} while ((i = next_desc(&desc)) != -1);
+
+	/* On success, increment avail index. */
+	vq->last_avail_idx++;
+	return head;
+}
+
+/* Reverse the effect of vhost_get_vq_desc. Useful for error handling. */
+void vhost_discard_vq_desc(struct vhost_virtqueue *vq)
+{
+	vq->last_avail_idx--;
+}
+
+/* After we've used one of their buffers, we tell them about it.  We'll then
+ * want to send them an interrupt, using vq->call. */
+int vhost_add_used(struct vhost_virtqueue *vq,
+			  unsigned int head, int len)
+{
+	struct vring_used_elem *used;
+
+	/* 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;
+	}
+	/* Make sure buffer is written before we update index. */
+	wmb();
+	if (put_user(vq->last_used_idx + 1, &vq->used->idx)) {
+		vq_err(vq, "Failed to increment used idx");
+		return -EFAULT;
+	}
+	if (unlikely(vq->log_used)) {
+		/* Make sure data is seen before log. */
+		wmb();
+		log_write(vq->log_base, vq->log_addr + sizeof *vq->used->ring *
+			  (vq->last_used_idx % vq->num),
+			  sizeof *vq->used->ring);
+		log_write(vq->log_base, vq->log_addr, sizeof *vq->used->ring);
+		if (vq->log_ctx)
+			eventfd_signal(vq->log_ctx, 1);
+	}
+	vq->last_used_idx++;
+	return 0;
+}
+
+/* This actually sends the interrupt for this virtqueue */
+void vhost_trigger_irq(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;
+	}
+
+	/* If they don't want an interrupt, don't send one, unless empty. */
+	if ((flags & VRING_AVAIL_F_NO_INTERRUPT) &&
+	    (vq->avail_idx != vq->last_avail_idx ||
+	     !vhost_has_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY)))
+		return;
+
+	/* Send the Guest an interrupt tell them we used something up. */
+	if (vq->call_ctx)
+		eventfd_signal(vq->call_ctx, 1);
+}
+
+/* And here's the combo meal deal.  Supersize me! */
+void vhost_add_used_and_trigger(struct vhost_dev *dev,
+				struct vhost_virtqueue *vq,
+				unsigned int head, int len)
+{
+	vhost_add_used(vq, head, len);
+	vhost_trigger_irq(dev, vq);
+}
+
+/* OK, now we need to know about added descriptors. */
+bool vhost_notify(struct vhost_virtqueue *vq)
+{
+	int r;
+	if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY))
+		return false;
+	vq->used_flags &= ~VRING_USED_F_NO_NOTIFY;
+	r = put_user(vq->used_flags, &vq->used->flags);
+	if (r)
+		vq_err(vq, "Failed to disable notification: %d\n", r);
+	/* They could have slipped one in as we were doing that: make
+	 * sure it's written, tell caller it needs to check again. */
+	mb();
+	return true;
+}
+
+/* We don't need to be notified again. */
+void vhost_no_notify(struct vhost_virtqueue *vq)
+{
+	int r;
+	if (vq->used_flags & VRING_USED_F_NO_NOTIFY)
+		return;
+	vq->used_flags |= VRING_USED_F_NO_NOTIFY;
+	r = put_user(vq->used_flags, &vq->used->flags);
+	if (r)
+		vq_err(vq, "Failed to enable notification: %d\n", r);
+}
+
+int vhost_init(void)
+{
+	vhost_workqueue = create_singlethread_workqueue("vhost");
+	if (!vhost_workqueue)
+		return -ENOMEM;
+	return 0;
+}
+
+void vhost_cleanup(void)
+{
+	destroy_workqueue(vhost_workqueue);
+}
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
new file mode 100644
index 0000000..d3900de
--- /dev/null
+++ b/drivers/vhost/vhost.h
@@ -0,0 +1,158 @@
+#ifndef _VHOST_H
+#define _VHOST_H
+
+#include <linux/eventfd.h>
+#include <linux/vhost.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
+#include <linux/file.h>
+#include <linux/skbuff.h>
+#include <linux/uio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+
+struct vhost_device;
+
+enum {
+	VHOST_NET_MAX_SG = MAX_SKB_FRAGS + 2,
+};
+
+/* Poll a file (eventfd or socket) */
+/* Note: there's nothing vhost specific about this structure. */
+struct vhost_poll {
+	poll_table                table;
+	wait_queue_head_t        *wqh;
+	wait_queue_t              wait;
+	/* struct which will handle all actual work. */
+	struct work_struct        work;
+	unsigned long		  mask;
+};
+
+void vhost_poll_init(struct vhost_poll *poll, work_func_t func,
+		     unsigned long mask);
+void vhost_poll_start(struct vhost_poll *poll, struct file *file);
+void vhost_poll_stop(struct vhost_poll *poll);
+void vhost_poll_flush(struct vhost_poll *poll);
+void vhost_poll_queue(struct vhost_poll *poll);
+
+struct vhost_log {
+	u64 addr;
+	u64 len;
+};
+
+/* The virtqueue structure describes a queue attached to a device. */
+struct vhost_virtqueue {
+	struct vhost_dev *dev;
+
+	/* The actual ring of buffers. */
+	struct mutex mutex;
+	unsigned int num;
+	struct vring_desc __user *desc;
+	struct vring_avail __user *avail;
+	struct vring_used __user *used;
+	struct file *kick;
+	struct file *call;
+	struct file *error;
+	struct eventfd_ctx *call_ctx;
+	struct eventfd_ctx *error_ctx;
+	struct eventfd_ctx *log_ctx;
+
+	struct vhost_poll poll;
+
+	/* The routine to call when the Guest pings us, or timeout. */
+	work_func_t handle_kick;
+
+	/* Last available index we saw. */
+	u16 last_avail_idx;
+
+	/* Caches available index value from user. */
+	u16 avail_idx;
+
+	/* Last index we used. */
+	u16 last_used_idx;
+
+	/* Used flags */
+	u16 used_flags;
+
+	/* Log writes to used structure. */
+	bool log_used;
+	u64 log_addr;
+
+	struct iovec indirect[VHOST_NET_MAX_SG];
+	struct iovec iov[VHOST_NET_MAX_SG];
+	struct iovec hdr[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
+	 * flush the workqueue instead of synchronize_rcu. Therefore readers do
+	 * not need to call rcu_read_lock/rcu_read_unlock: the beginning of
+	 * work item execution acts instead of rcu_read_lock() and the end of
+	 * work item execution acts instead of rcu_read_lock().
+	 * Writers use virtqueue mutex. */
+	void *private_data;
+	/* Log write descriptors */
+	void __user *log_base;
+	struct vhost_log log[VHOST_NET_MAX_SG];
+};
+
+struct vhost_dev {
+	/* Readers use RCU to access memory table pointer
+	 * log base pointer and features.
+	 * Writers use mutex below.*/
+	struct vhost_memory *memory;
+	struct mm_struct *mm;
+	struct mutex mutex;
+	unsigned acked_features;
+	struct vhost_virtqueue *vqs;
+	int nvqs;
+	struct file *log_file;
+	struct eventfd_ctx *log_ctx;
+};
+
+long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue *vqs, int nvqs);
+long vhost_dev_check_owner(struct vhost_dev *);
+long vhost_dev_reset_owner(struct vhost_dev *);
+void vhost_dev_cleanup(struct vhost_dev *);
+long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);
+
+unsigned vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *,
+			   struct iovec iov[],
+			   unsigned int *out_num, unsigned int *in_num,
+			   struct vhost_log *log, unsigned int *log_num);
+void vhost_discard_vq_desc(struct vhost_virtqueue *);
+
+int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len);
+void vhost_trigger_irq(struct vhost_dev *, struct vhost_virtqueue *);
+void vhost_add_used_and_trigger(struct vhost_dev *, struct vhost_virtqueue *,
+				unsigned int head, int len);
+void vhost_no_notify(struct vhost_virtqueue *);
+bool vhost_notify(struct vhost_virtqueue *);
+
+int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
+		    unsigned int log_num, u64 len);
+
+int vhost_init(void);
+void vhost_cleanup(void);
+
+#define vq_err(vq, fmt, ...) do {                                  \
+		pr_debug(pr_fmt(fmt), ##__VA_ARGS__);       \
+		if ((vq)->error_ctx)                               \
+				eventfd_signal((vq)->error_ctx, 1);\
+	} while (0)
+
+enum {
+	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),
+};
+
+static inline int vhost_has_feature(struct vhost_dev *dev, int bit)
+{
+	unsigned acked_features = rcu_dereference(dev->acked_features);
+	return acked_features & (1 << bit);
+}
+
+#endif
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 3f384d4..b6335c6 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -361,6 +361,7 @@ unifdef-y += uio.h
 unifdef-y += unistd.h
 unifdef-y += usbdevice_fs.h
 unifdef-y += utsname.h
+unifdef-y += vhost.h
 unifdef-y += videodev2.h
 unifdef-y += videodev.h
 unifdef-y += virtio_config.h
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index adaf3c1..8b5f7cc 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -30,6 +30,7 @@
 #define HPET_MINOR		228
 #define FUSE_MINOR		229
 #define KVM_MINOR		232
+#define VHOST_NET_MINOR		233
 #define MISC_DYNAMIC_MINOR	255
 
 struct device;
diff --git a/include/linux/vhost.h b/include/linux/vhost.h
new file mode 100644
index 0000000..f66142f
--- /dev/null
+++ b/include/linux/vhost.h
@@ -0,0 +1,126 @@
+#ifndef _LINUX_VHOST_H
+#define _LINUX_VHOST_H
+/* Userspace interface for in-kernel virtio accelerators. */
+
+/* vhost is used to reduce the number of system calls involved in virtio.
+ *
+ * Existing virtio net code is used in the guest without modification.
+ *
+ * This header includes interface used by userspace hypervisor for
+ * device configuration.
+ */
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/ioctl.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+
+struct vhost_vring_state {
+	unsigned int index;
+	unsigned int num;
+};
+
+struct vhost_vring_file {
+	unsigned int index;
+	int fd; /* Pass -1 to unbind from file. */
+
+};
+
+struct vhost_vring_addr {
+	unsigned int index;
+	unsigned int padding;
+	__u64 user_addr;
+};
+
+struct vhost_memory_region {
+	__u64 guest_phys_addr;
+	__u64 memory_size; /* bytes */
+	__u64 userspace_addr;
+	__u64 flags_padding; /* No flags are currently specified. */
+};
+
+/* All region addresses and sizes must be 4K aligned. */
+#define VHOST_PAGE_SIZE 0x1000
+
+struct vhost_memory {
+	__u32 nregions;
+	__u32 padding;
+	struct vhost_memory_region regions[0];
+};
+
+/* ioctls */
+
+#define VHOST_VIRTIO 0xAF
+
+/* Features bitmask for forward compatibility.  Transport bits are used for
+ * vhost specific features. */
+#define VHOST_GET_FEATURES	_IOR(VHOST_VIRTIO, 0x00, __u64)
+#define VHOST_ACK_FEATURES	_IOW(VHOST_VIRTIO, 0x00, __u64)
+
+/* Set current process as the (exclusive) owner of this file descriptor.  This
+ * must be called before any other vhost command.  Further calls to
+ * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
+#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
+/* Give up ownership, and reset the device to default values.
+ * Allows subsequent call to VHOST_OWNER_SET to succeed. */
+#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
+
+/* Set up/modify memory layout */
+#define VHOST_SET_MEM_TABLE	_IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
+
+/* Write logging setup. */
+/* Memory writes can optionally be logged by setting bit at an offset
+ * (calculated from the physical address) from specified log base.
+ * The bit is set using an atomic 32 bit operation. */
+/* Set base address for logging. */
+#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
+/* Specify an eventfd file descriptor to signal on log write. */
+#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
+
+/* Ring setup. These parameters can not be modified while ring is running
+ * (bound to a device). */
+/* Set number of descriptors in ring */
+#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
+/* Start of array of descriptors (virtually contiguous) */
+#define VHOST_SET_VRING_DESC _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
+/* Used structure address. Must be 32 bit aligned */
+#define VHOST_SET_VRING_USED _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_addr)
+/* Available structure address. Must be 16 bit aligned */
+#define VHOST_SET_VRING_AVAIL _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_addr)
+/* Base value where queue looks for available descriptors */
+#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x14, struct vhost_vring_state)
+/* Get accessor: reads index, writes value in num */
+#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x14, struct vhost_vring_state)
+
+/* Logging support. Can be modified while ring is running. */
+/* Log writes to used structure, at offset calculated from specified address.
+ * Address must be 32 bit aligned. Pass 0x1 to disable logging. */
+#define VHOST_SET_VRING_LOG _IOW(VHOST_VIRTIO, 0x18, struct vhost_vring_addr)
+#define VHOST_VRING_LOG_DISABLE (0x1)
+
+/* The following ioctls use eventfd file descriptors to signal and poll
+ * for events. */
+
+/* Set eventfd to poll for added buffers */
+#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
+/* Set eventfd to signal when buffers have beed used */
+#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
+/* Set eventfd to signal an error */
+#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
+
+/* VHOST_NET specific defines */
+
+/* Attach virtio net ring to a raw socket, or tap device.
+ * The socket must be already bound to an ethernet device, this device will be
+ * used for transmit.  Pass fd -1 to unbind from the socket and the transmit
+ * device.  This can be used to stop the ring (e.g. for migration). */
+#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
+
+/* Feature bits */
+/* Log all write descriptors. Can be changed while device is active. */
+#define VHOST_F_LOG_ALL 26
+/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
+#define VHOST_NET_F_VIRTIO_NET_HDR 27
+
+#endif
-- 
1.6.5.2.143.g8cc62

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply related

* Re: [PATCHv7 2/3] mm: export use_mm/unuse_mm to modules
From: Gregory Haskins @ 2009-11-03 17:32 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, akpm,
	hpa, Rusty Russell, s.hetze
In-Reply-To: <20091103172411.GC5591@redhat.com>

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

Michael S. Tsirkin wrote:
> vhost net module wants to do copy to/from user from a kernel thread,
> which needs use_mm. Export it to modules.
> 
> Acked-by: Andrea Arcangeli <aarcange@redhat.com>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

I need this too:

Acked-by: Gregory Haskins <ghaskins@novell.com>

> ---
>  mm/mmu_context.c |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
> 
> diff --git a/mm/mmu_context.c b/mm/mmu_context.c
> index ded9081..0777654 100644
> --- a/mm/mmu_context.c
> +++ b/mm/mmu_context.c
> @@ -5,6 +5,7 @@
>  
>  #include <linux/mm.h>
>  #include <linux/mmu_context.h>
> +#include <linux/module.h>
>  #include <linux/sched.h>
>  
>  #include <asm/mmu_context.h>
> @@ -37,6 +38,7 @@ void use_mm(struct mm_struct *mm)
>  	if (active_mm != mm)
>  		mmdrop(active_mm);
>  }
> +EXPORT_SYMBOL_GPL(use_mm);
>  
>  /*
>   * unuse_mm
> @@ -56,3 +58,4 @@ void unuse_mm(struct mm_struct *mm)
>  	enter_lazy_tlb(mm, tsk);
>  	task_unlock(tsk);
>  }
> +EXPORT_SYMBOL_GPL(unuse_mm);



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 267 bytes --]

^ permalink raw reply

* 2.6.32-rc5-mmotm1101 - kernel BUG at net/ipv4/tcp_input.c:3707!
From: Valdis.Kletnieks @ 2009-11-03 17:50 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel, netdev

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

Seen right after I started 'fetchmail'.  Reproducible - 3 out of 3.
I'll bisect this tonight if nobody jumps up and yells they know what it is...

Looking at the traceback, I wonder if we started sending the SYN packet,
but didn't finish the paperwork before the SYN/ACK came back?

[   87.269743] ------------[ cut here ]------------
[   87.270011] kernel BUG at net/ipv4/tcp_input.c:3707!
[   87.270011] invalid opcode: 0000 [#1] PREEMPT SMP 
[   87.270011] last sysfs file: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:00/power_supply/BAT0/charge_full
[   87.270011] CPU 0 
[   87.270011] Modules linked in: ext4 jbd2 crc16 [last unloaded: microcode]
[   87.270011] Pid: 2421, comm: fetchmail Not tainted 2.6.32-rc5-mmotm1101 #1 Latitude D820                   
[   87.270011] RIP: 0010:[<ffffffff813d13c2>]  [<ffffffff813d13c2>] tcp_parse_options+0x62/0x273
[   87.270011] RSP: 0018:ffff880002603af8  EFLAGS: 00010202
[   87.270011] RAX: 0000000000000001 RBX: ffff880002603b78 RCX: 000000000000000a
[   87.270011] RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffff81ad9fb0
[   87.270011] RBP: ffff880002603b48 R08: ffff88007e2d9000 R09: 0000000000000001
[   87.270011] R10: 00000000000006f6 R11: ffff880002603a78 R12: 0000000000000000
[   87.270011] R13: ffff88007eb0ece8 R14: 0000000000000000 R15: ffff88007e693168
[   87.270011] FS:  00007fa02ff827c0(0000) GS:ffff880002600000(0000) knlGS:0000000000000000
[   87.270011] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   87.270011] CR2: 00000032cf7411e0 CR3: 000000007e41d000 CR4: 00000000000006f0
[   87.270011] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   87.270011] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[   87.270011] Process fetchmail (pid: 2421, threadinfo ffff880079234000, task ffff88007d2bc300)
[   87.270011] Stack:
[   87.270011]  ffff880002603b48 ffffffff00000001 000000000000000a ffffffff00000000
[   87.270011] <0> 0000000000000000 ffff88007903bbc0 ffff88007e693168 ffff88007c6eb2c0
[   87.270011] <0> 0000000000000000 0000000000000000 ffff880002603bc8 ffffffff81430486
[   87.270011] Call Trace:
[   87.270011]  <IRQ> 
[   87.270011]  [<ffffffff81430486>] tcp_v6_conn_request+0x171/0x3cb
[   87.270011]  [<ffffffff813d3bf8>] tcp_rcv_state_process+0x5f/0x857
[   87.270011]  [<ffffffff8142ff4d>] tcp_v6_do_rcv+0x313/0x445
[   87.270011]  [<ffffffff814bd489>] ? _spin_lock_nested+0x42/0x49
[   87.270011]  [<ffffffff8143155b>] ? tcp_v6_rcv+0x2aa/0x61c
[   87.270011]  [<ffffffff814316f6>] tcp_v6_rcv+0x445/0x61c
[   87.270011]  [<ffffffff81414bb9>] ip6_input_finish+0x1bf/0x31f
[   87.270011]  [<ffffffff81414d66>] ip6_input+0x4d/0x54
[   87.270011]  [<ffffffff81414502>] ip6_rcv_finish+0x22/0x26
[   87.270011]  [<ffffffff81414964>] ipv6_rcv+0x45e/0x4b4
[   87.270011]  [<ffffffff81391662>] netif_receive_skb+0x29e/0x2c8
[   87.270011]  [<ffffffff81391717>] process_backlog+0x8b/0xc1
[   87.270011]  [<ffffffff81391e6a>] net_rx_action+0xed/0x2b0
[   87.270011]  [<ffffffff8108518a>] ? handle_edge_irq+0x16a/0x176
[   87.270011]  [<ffffffff81041c2a>] __do_softirq+0x127/0x23c
[   87.270011]  [<ffffffff813922f4>] ? rcu_read_unlock_bh+0x21/0x23
[   87.270011]  [<ffffffff8100347c>] call_softirq+0x1c/0x34
[   87.270011]  <EOI> 
[   87.270011]  [<ffffffff810049cc>] do_softirq+0x44/0xf0
[   87.270011]  [<ffffffff813922f4>] ? rcu_read_unlock_bh+0x21/0x23
[   87.270011]  [<ffffffff810414c7>] _local_bh_enable_ip+0x120/0x16e
[   87.270011]  [<ffffffff8104152d>] local_bh_enable+0xd/0xf
[   87.270011]  [<ffffffff813922f4>] rcu_read_unlock_bh+0x21/0x23
[   87.270011]  [<ffffffff81392e10>] dev_queue_xmit+0x3e4/0x408
[   87.270011]  [<ffffffff81392b70>] ? dev_queue_xmit+0x144/0x408
[   87.270011]  [<ffffffff8139afa8>] neigh_resolve_output+0x1ef/0x240
[   87.270011]  [<ffffffff81410f50>] ? ip6_output_finish+0x0/0xfc
[   87.270011]  [<ffffffff81410fec>] ip6_output_finish+0x9c/0xfc
[   87.270011]  [<ffffffff8141242d>] ip6_output2+0x2bf/0x2c8
[   87.270011]  [<ffffffff81413107>] ip6_output+0xcd1/0xce6
[   87.270011]  [<ffffffff813ab63a>] ? rcu_read_unlock+0x21/0x23
[   87.270011]  [<ffffffff813ab89b>] ? nf_hook_slow+0xca/0xdb
[   87.270011]  [<ffffffff81410c9c>] ? dst_output+0x0/0xd
[   87.270011]  [<ffffffff81410ca7>] dst_output+0xb/0xd
[   87.270011]  [<ffffffff81413517>] ip6_xmit+0x3fb/0x4d4
[   87.270011]  [<ffffffff8143dba6>] ? __inet6_hash+0xe5/0x122
[   87.270011]  [<ffffffff814358b2>] inet6_csk_xmit+0x265/0x274
[   87.270011]  [<ffffffff811caa4c>] ? _raw_spin_lock+0xe9/0x1ab
[   87.270011]  [<ffffffff813d557d>] tcp_transmit_skb+0x816/0x85f
[   87.270011]  [<ffffffff813d6ed5>] tcp_connect+0x3ae/0x409
[   87.270011]  [<ffffffff8142f74f>] tcp_v6_connect+0x4f0/0x55e
[   87.270011]  [<ffffffff813e78d0>] inet_stream_connect+0xa0/0x268
[   87.270011]  [<ffffffff81383c71>] sys_connect+0x75/0x98
[   87.270011]  [<ffffffff810e2328>] ? path_put+0x1d/0x22
[   87.270011]  [<ffffffff81066193>] ? trace_hardirqs_on_caller+0x16/0x13c
[   87.270011]  [<ffffffff8107fdf1>] ? audit_syscall_entry+0xcb/0x19c
[   87.270011]  [<ffffffff8100246b>] system_call_fastpath+0x16/0x1b
[   87.270011] Code: e9 04 4d 85 f6 88 4d c0 0f 94 c2 31 c0 45 85 e4 0f 94 c0 21 d0 31 d2 89 c6 89 45 b8 e8 70 6a cc ff 8b 45 b8 8a 4d c0 85 c0 74 04 <0f> 0b eb fe 0f b6 d1 49 83 c7 38 8d 14 95 ec ff ff ff 49 8d 45 
[   87.270011] RIP  [<ffffffff813d13c2>] tcp_parse_options+0x62/0x273
[   87.270011]  RSP <ffff880002603af8>


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

^ permalink raw reply

* Re: [PATCH 1/3] sysfs directory scaling: rbtree for dirent name lookups
From: Greg KH @ 2009-11-03 17:56 UTC (permalink / raw)
  To: Benjamin LaHaise
  Cc: Eric Dumazet, Eric W. Biederman, Octavian Purdila, netdev,
	Cosmin Ratiu, linux-kernel
In-Reply-To: <20091103164550.GM8227@kvack.org>

On Tue, Nov 03, 2009 at 11:45:50AM -0500, Benjamin LaHaise wrote:
> On Tue, Nov 03, 2009 at 08:07:15AM -0800, Greg KH wrote:
> > But registering 20000 devices is a far different problem from using
> > those 20000 devices :)
> 
> Registering 20,000 devices *is* a real world problem (I'm actually aiming 
> for 100,000, as that's what roughly fits in a single 10Gbps link -- something 
> that a mid range system can now route).  When an edge router comes up from 
> reboot, or after a link has been down, the rate at which customers connect 
> is important -- too slow, and you get a pile of support calls from customers 
> complaining that their connection is down.  Because of the data structures 
> used, there isn't even any improvement from an SMP system, so this needs 
> to be addressed directly.

Ok, how long are we talking about here?

thanks,

greg k-h

^ permalink raw reply

* Re: 2.6.32-rc5-mmotm1101 - kernel BUG at net/ipv4/tcp_input.c:3707!
From: Eric Dumazet @ 2009-11-03 18:02 UTC (permalink / raw)
  To: Valdis.Kletnieks
  Cc: Andrew Morton, linux-kernel, netdev, Gilad Ben-Yossef,
	Ori Finkelman
In-Reply-To: <5765.1257270611@turing-police.cc.vt.edu>

Valdis.Kletnieks@vt.edu a écrit :
> Seen right after I started 'fetchmail'.  Reproducible - 3 out of 3.
> I'll bisect this tonight if nobody jumps up and yells they know what it is...
> 
> Looking at the traceback, I wonder if we started sending the SYN packet,
> but didn't finish the paperwork before the SYN/ACK came back?
> 
> [   87.269743] ------------[ cut here ]------------
> [   87.270011] kernel BUG at net/ipv4/tcp_input.c:3707!
> [   87.270011] invalid opcode: 0000 [#1] PREEMPT SMP 
> [   87.270011] last sysfs file: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0A:00/power_supply/BAT0/charge_full
> [   87.270011] CPU 0 
> [   87.270011] Modules linked in: ext4 jbd2 crc16 [last unloaded: microcode]
> [   87.270011] Pid: 2421, comm: fetchmail Not tainted 2.6.32-rc5-mmotm1101 #1 Latitude D820                   
> [   87.270011] RIP: 0010:[<ffffffff813d13c2>]  [<ffffffff813d13c2>] tcp_parse_options+0x62/0x273
> [   87.270011] RSP: 0018:ffff880002603af8  EFLAGS: 00010202
> [   87.270011] RAX: 0000000000000001 RBX: ffff880002603b78 RCX: 000000000000000a
> [   87.270011] RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffff81ad9fb0
> [   87.270011] RBP: ffff880002603b48 R08: ffff88007e2d9000 R09: 0000000000000001
> [   87.270011] R10: 00000000000006f6 R11: ffff880002603a78 R12: 0000000000000000
> [   87.270011] R13: ffff88007eb0ece8 R14: 0000000000000000 R15: ffff88007e693168
> [   87.270011] FS:  00007fa02ff827c0(0000) GS:ffff880002600000(0000) knlGS:0000000000000000
> [   87.270011] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   87.270011] CR2: 00000032cf7411e0 CR3: 000000007e41d000 CR4: 00000000000006f0
> [   87.270011] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [   87.270011] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> [   87.270011] Process fetchmail (pid: 2421, threadinfo ffff880079234000, task ffff88007d2bc300)
> [   87.270011] Stack:
> [   87.270011]  ffff880002603b48 ffffffff00000001 000000000000000a ffffffff00000000
> [   87.270011] <0> 0000000000000000 ffff88007903bbc0 ffff88007e693168 ffff88007c6eb2c0
> [   87.270011] <0> 0000000000000000 0000000000000000 ffff880002603bc8 ffffffff81430486
> [   87.270011] Call Trace:
> [   87.270011]  <IRQ> 
> [   87.270011]  [<ffffffff81430486>] tcp_v6_conn_request+0x171/0x3cb
> [   87.270011]  [<ffffffff813d3bf8>] tcp_rcv_state_process+0x5f/0x857
> [   87.270011]  [<ffffffff8142ff4d>] tcp_v6_do_rcv+0x313/0x445
> [   87.270011]  [<ffffffff814bd489>] ? _spin_lock_nested+0x42/0x49
> [   87.270011]  [<ffffffff8143155b>] ? tcp_v6_rcv+0x2aa/0x61c
> [   87.270011]  [<ffffffff814316f6>] tcp_v6_rcv+0x445/0x61c
> [   87.270011]  [<ffffffff81414bb9>] ip6_input_finish+0x1bf/0x31f
> [   87.270011]  [<ffffffff81414d66>] ip6_input+0x4d/0x54
> [   87.270011]  [<ffffffff81414502>] ip6_rcv_finish+0x22/0x26
> [   87.270011]  [<ffffffff81414964>] ipv6_rcv+0x45e/0x4b4
> [   87.270011]  [<ffffffff81391662>] netif_receive_skb+0x29e/0x2c8
> [   87.270011]  [<ffffffff81391717>] process_backlog+0x8b/0xc1
> [   87.270011]  [<ffffffff81391e6a>] net_rx_action+0xed/0x2b0
> [   87.270011]  [<ffffffff8108518a>] ? handle_edge_irq+0x16a/0x176
> [   87.270011]  [<ffffffff81041c2a>] __do_softirq+0x127/0x23c
> [   87.270011]  [<ffffffff813922f4>] ? rcu_read_unlock_bh+0x21/0x23
> [   87.270011]  [<ffffffff8100347c>] call_softirq+0x1c/0x34
> [   87.270011]  <EOI> 
> [   87.270011]  [<ffffffff810049cc>] do_softirq+0x44/0xf0
> [   87.270011]  [<ffffffff813922f4>] ? rcu_read_unlock_bh+0x21/0x23
> [   87.270011]  [<ffffffff810414c7>] _local_bh_enable_ip+0x120/0x16e
> [   87.270011]  [<ffffffff8104152d>] local_bh_enable+0xd/0xf
> [   87.270011]  [<ffffffff813922f4>] rcu_read_unlock_bh+0x21/0x23
> [   87.270011]  [<ffffffff81392e10>] dev_queue_xmit+0x3e4/0x408
> [   87.270011]  [<ffffffff81392b70>] ? dev_queue_xmit+0x144/0x408
> [   87.270011]  [<ffffffff8139afa8>] neigh_resolve_output+0x1ef/0x240
> [   87.270011]  [<ffffffff81410f50>] ? ip6_output_finish+0x0/0xfc
> [   87.270011]  [<ffffffff81410fec>] ip6_output_finish+0x9c/0xfc
> [   87.270011]  [<ffffffff8141242d>] ip6_output2+0x2bf/0x2c8
> [   87.270011]  [<ffffffff81413107>] ip6_output+0xcd1/0xce6
> [   87.270011]  [<ffffffff813ab63a>] ? rcu_read_unlock+0x21/0x23
> [   87.270011]  [<ffffffff813ab89b>] ? nf_hook_slow+0xca/0xdb
> [   87.270011]  [<ffffffff81410c9c>] ? dst_output+0x0/0xd
> [   87.270011]  [<ffffffff81410ca7>] dst_output+0xb/0xd
> [   87.270011]  [<ffffffff81413517>] ip6_xmit+0x3fb/0x4d4
> [   87.270011]  [<ffffffff8143dba6>] ? __inet6_hash+0xe5/0x122
> [   87.270011]  [<ffffffff814358b2>] inet6_csk_xmit+0x265/0x274
> [   87.270011]  [<ffffffff811caa4c>] ? _raw_spin_lock+0xe9/0x1ab
> [   87.270011]  [<ffffffff813d557d>] tcp_transmit_skb+0x816/0x85f
> [   87.270011]  [<ffffffff813d6ed5>] tcp_connect+0x3ae/0x409
> [   87.270011]  [<ffffffff8142f74f>] tcp_v6_connect+0x4f0/0x55e
> [   87.270011]  [<ffffffff813e78d0>] inet_stream_connect+0xa0/0x268
> [   87.270011]  [<ffffffff81383c71>] sys_connect+0x75/0x98
> [   87.270011]  [<ffffffff810e2328>] ? path_put+0x1d/0x22
> [   87.270011]  [<ffffffff81066193>] ? trace_hardirqs_on_caller+0x16/0x13c
> [   87.270011]  [<ffffffff8107fdf1>] ? audit_syscall_entry+0xcb/0x19c
> [   87.270011]  [<ffffffff8100246b>] system_call_fastpath+0x16/0x1b
> [   87.270011] Code: e9 04 4d 85 f6 88 4d c0 0f 94 c2 31 c0 45 85 e4 0f 94 c0 21 d0 31 d2 89 c6 89 45 b8 e8 70 6a cc ff 8b 45 b8 8a 4d c0 85 c0 74 04 <0f> 0b eb fe 0f b6 d1 49 83 c7 38 8d 14 95 ec ff ff ff 49 8d 45 
> [   87.270011] RIP  [<ffffffff813d13c2>] tcp_parse_options+0x62/0x273
> [   87.270011]  RSP <ffff880002603af8>
> 


BUG_ON(!estab && !dst); 

Probably comes from commit 022c3f7d82f0f1c68018696f2f027b87b9bb45c2

(Allow tcp_parse_options to consult dst entry)

CC Gilad Ben-Yossef <gilad@codefidence.com> and Ori Finkelman <ori@comsleep.com> for a diagnostic

^ permalink raw reply

* Re: [PATCHv7 3/3] vhost_net: a kernel-level virtio server
From: Eric Dumazet @ 2009-11-03 18:03 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: netdev, virtualization, kvm, linux-kernel, mingo, linux-mm, akpm,
	hpa, gregory.haskins, Rusty Russell, s.hetze, Paul E. McKenney
In-Reply-To: <20091103172422.GD5591@redhat.com>

Michael S. Tsirkin a écrit :
> +static void handle_tx(struct vhost_net *net)
> +{
> +	struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_TX];
> +	unsigned head, out, in, s;
> +	struct msghdr msg = {
> +		.msg_name = NULL,
> +		.msg_namelen = 0,
> +		.msg_control = NULL,
> +		.msg_controllen = 0,
> +		.msg_iov = vq->iov,
> +		.msg_flags = MSG_DONTWAIT,
> +	};
> +	size_t len, total_len = 0;
> +	int err, wmem;
> +	size_t hdr_size;
> +	struct socket *sock = rcu_dereference(vq->private_data);
> +	if (!sock)
> +		return;
> +
> +	wmem = atomic_read(&sock->sk->sk_wmem_alloc);
> +	if (wmem >= sock->sk->sk_sndbuf)
> +		return;
> +
> +	use_mm(net->dev.mm);
> +	mutex_lock(&vq->mutex);
> +	vhost_no_notify(vq);
> +

using rcu_dereference() and mutex_lock() at the same time seems wrong, I suspect
that your use of RCU is not correct.

1) rcu_dereference() should be done inside a read_rcu_lock() section, and
   we are not allowed to sleep in such a section.
   (Quoting Documentation/RCU/whatisRCU.txt :
     It is illegal to block while in an RCU read-side critical section, )

2) mutex_lock() can sleep (ie block)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH] iproute2: Avoid rounding errors for 100%.
From: Stephen Hemminger @ 2009-11-03 18:05 UTC (permalink / raw)
  To: Arnd Hannemann; +Cc: netdev@vger.kernel.org
In-Reply-To: <4AF06617.6030804@nets.rwth-aachen.de>

On Tue, 03 Nov 2009 18:19:19 +0100
Arnd Hannemann <hannemann@nets.rwth-aachen.de> wrote:

> Stephen Hemminger wrote:
> > On Tue, 03 Nov 2009 17:19:45 +0100
> > Arnd Hannemann <hannemann@nets.rwth-aachen.de> wrote:
> > 
> >> Although the patch makes sense,
> >> it does not fix the bug/effect we were seeing.
> >> A netem reorder percentage of 100% will still get packets reordered.
> >> (if the netem queue is not empty)
> >>
> >>
> >> hannemann@nets.rwth-aachen.de wrote:
> >>> From: Arnd Hannemann <hannemann@nets.rwth-aachen.de>
> >>>
> >>> We noticed that a netem reorder percentage of 100% will still get packets reordered.
> >>> This patch fixes that.
> >>>
> >>> Signed-off-by: Arnd Hannemann <hannemann@nets.rwth-aachen.de>
> >>> ---
> >>>  tc/tc_util.c |    6 ++++--
> >>>  1 files changed, 4 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/tc/tc_util.c b/tc/tc_util.c
> >>> index fe2c7eb..2641f2e 100644
> >>> --- a/tc/tc_util.c
> >>> +++ b/tc/tc_util.c
> >>> @@ -363,8 +363,10 @@ int get_percent(__u32 *percent, const char *str)
> >>>  		return -1;
> >>>  	if (*p && strcmp(p, "%"))
> >>>  		return -1;
> >>> -
> >>> -	*percent = (unsigned) rint(per * max_percent_value);
> >>> +	if (per == 1.)
> >>> +		*percent = max_percent_value;
> >>> +	else
> >>> +		*percent = (unsigned) rint(per * max_percent_value);
> >>>  	return 0;
> >>>  }
> >>>  
> >>
> > 
> > If you don't want reordering, don't specify reordering?
> 
> Are you arguing against the correctness of my patch?
> 
> Regarding, the reordering thingy/bug/effect whatever:
> We would like to specify reordering with something like this:
> Please delay 1% of the packets with 5ms.
> 
> We thought that would be possible with
> tc qdisc add dev eth0 root netem delay 5m reorder 99%
> 
> But unfortunately it is not. Any better idea?
> 

I think the problem isn't in iproute utilities but in the code inside
netem kernel module. 

-- 

^ permalink raw reply


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