[linux-yocto] [PATCH 06/29] openvswitch: flow_netlink: Use pr_fmt to OVS_NLERR output

2014-08-20 Thread zhe.he
From: Joe Perches j...@perches.com

commit 2235ad1c3ac545bd8fc2c026be5be16d98b9a891 upstream

Add openvswitch:  prefix to OVS_NLERR output
to match the other OVS_NLERR output of datapath.c

Signed-off-by: Joe Perches j...@perches.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/flow_netlink.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 1b22ad2..7bd09b7 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -16,6 +16,8 @@
  * 02110-1301, USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME :  fmt
+
 #include flow.h
 #include datapath.h
 #include linux/uaccess.h
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 01/29] openvswitch: use const in some local vars and casts

2014-08-20 Thread zhe.he
From: Daniele Di Proietto daniele.di.proie...@gmail.com

commit 7085130bab2f9c5b8d61bff73b01dc8195d0f974 upstream

In few functions, const formal parameters are assigned or cast to
non-const.
These changes suppress warnings if compiled with -Wcast-qual.

Signed-off-by: Daniele Di Proietto daniele.di.proie...@gmail.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/flow_netlink.c |  6 --
 net/openvswitch/flow_table.c   | 16 +---
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 4d000ac..5517bd6 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -628,8 +628,10 @@ static int ovs_key_from_nlattrs(struct sw_flow_match 
*match,  bool *exact_5tuple
 
if (is_mask  exact_5tuple  *exact_5tuple) {
if (ipv6_key-ipv6_proto != 0xff ||
-   !is_all_set((u8 *)ipv6_key-ipv6_src, 
sizeof(match-key-ipv6.addr.src)) ||
-   !is_all_set((u8 *)ipv6_key-ipv6_dst, 
sizeof(match-key-ipv6.addr.dst)))
+   !is_all_set((const u8 *)ipv6_key-ipv6_src,
+   sizeof(match-key-ipv6.addr.src)) ||
+   !is_all_set((const u8 *)ipv6_key-ipv6_dst,
+   sizeof(match-key-ipv6.addr.dst)))
*exact_5tuple = false;
}
}
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index 3c268b3..1ba1e0b 100644
--- a/net/openvswitch/flow_table.c
+++ b/net/openvswitch/flow_table.c
@@ -57,8 +57,10 @@ static u16 range_n_bytes(const struct sw_flow_key_range 
*range)
 void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
   const struct sw_flow_mask *mask)
 {
-   const long *m = (long *)((u8 *)mask-key + mask-range.start);
-   const long *s = (long *)((u8 *)src + mask-range.start);
+   const long *m = (const long *)((const u8 *)mask-key +
+   mask-range.start);
+   const long *s = (const long *)((const u8 *)src +
+   mask-range.start);
long *d = (long *)((u8 *)dst + mask-range.start);
int i;
 
@@ -375,7 +377,7 @@ int ovs_flow_tbl_flush(struct flow_table *flow_table)
 static u32 flow_hash(const struct sw_flow_key *key, int key_start,
 int key_end)
 {
-   u32 *hash_key = (u32 *)((u8 *)key + key_start);
+   const u32 *hash_key = (const u32 *)((const u8 *)key + key_start);
int hash_u32s = (key_end - key_start)  2;
 
/* Make sure number of hash bytes are multiple of u32. */
@@ -397,8 +399,8 @@ static bool cmp_key(const struct sw_flow_key *key1,
const struct sw_flow_key *key2,
int key_start, int key_end)
 {
-   const long *cp1 = (long *)((u8 *)key1 + key_start);
-   const long *cp2 = (long *)((u8 *)key2 + key_start);
+   const long *cp1 = (const long *)((const u8 *)key1 + key_start);
+   const long *cp2 = (const long *)((const u8 *)key2 + key_start);
long diffs = 0;
int i;
 
@@ -513,8 +515,8 @@ static struct sw_flow_mask *mask_alloc(void)
 static bool mask_equal(const struct sw_flow_mask *a,
   const struct sw_flow_mask *b)
 {
-   u8 *a_ = (u8 *)a-key + a-range.start;
-   u8 *b_ = (u8 *)b-key + b-range.start;
+   const u8 *a_ = (const u8 *)a-key + a-range.start;
+   const u8 *b_ = (const u8 *)b-key + b-range.start;
 
return  (a-range.end == b-range.end)
 (a-range.start == b-range.start)
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 02/29] openvswitch: avoid warnings in vport_from_priv

2014-08-20 Thread zhe.he
From: Daniele Di Proietto daniele.di.proie...@gmail.com

commit d0b4da137508db3d38998eae7f62c0f9699ee08c upstream

This change, firstly, avoids declaring the formal parameter const,
since it is treated as non const. (to avoid -Wcast-qual)
Secondly, it cast the pointer from void* to u8*, since it is used
in arithmetic (to avoid -Wpointer-arith)

Signed-off-by: Daniele Di Proietto daniele.di.proie...@gmail.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/vport.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index d7e50a1..3e12940 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -185,9 +185,9 @@ static inline void *vport_priv(const struct vport *vport)
  * the result of a hash table lookup.  @priv must point to the start of the
  * private data area.
  */
-static inline struct vport *vport_from_priv(const void *priv)
+static inline struct vport *vport_from_priv(void *priv)
 {
-   return (struct vport *)(priv - ALIGN(sizeof(struct vport), 
VPORT_ALIGN));
+   return (struct vport *)((u8 *)priv - ALIGN(sizeof(struct vport), 
VPORT_ALIGN));
 }
 
 void ovs_vport_receive(struct vport *, struct sk_buff *,
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 04/29] openvswitch: Added (unsigned long long) cast in printf

2014-08-20 Thread zhe.he
From: Daniele Di Proietto daniele.di.proie...@gmail.com

commit cc23ebf3bb4348fb022c0d25494307459bb2e539 upstream

This is necessary, since u64 is not unsigned long long
in all architectures: u64 could be also uint64_t.

Signed-off-by: Daniele Di Proietto daniele.di.proie...@gmail.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/flow_netlink.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 5517bd6..1b22ad2 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -216,14 +216,14 @@ static bool match_validate(const struct sw_flow_match 
*match,
if ((key_attrs  key_expected) != key_expected) {
/* Key attributes check failed. */
OVS_NLERR(Missing expected key attributes (key_attrs=%llx, 
expected=%llx).\n,
-   key_attrs, key_expected);
+   (unsigned long long)key_attrs, (unsigned long 
long)key_expected);
return false;
}
 
if ((mask_attrs  mask_allowed) != mask_attrs) {
/* Mask attributes check failed. */
OVS_NLERR(Contain more than allowed mask fields 
(mask_attrs=%llx, mask_allowed=%llx).\n,
-   mask_attrs, mask_allowed);
+   (unsigned long long)mask_attrs, (unsigned long 
long)mask_allowed);
return false;
}
 
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 03/29] openvswitch: avoid cast-qual warning in vport_priv

2014-08-20 Thread zhe.he
From: Daniele Di Proietto daniele.di.proie...@gmail.com

commit 07dc0602c5976cfc36ccffe5c6d73234f204d585 upstream

This function must cast a const value to a non const value.
By adding an uintptr_t cast the warning is suppressed.
To avoid the cast (proper solution) several function signatures
must be changed.

Signed-off-by: Daniele Di Proietto daniele.di.proie...@gmail.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/vport.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h
index 3e12940..8d721e6 100644
--- a/net/openvswitch/vport.h
+++ b/net/openvswitch/vport.h
@@ -172,7 +172,7 @@ void ovs_vport_deferred_free(struct vport *vport);
  */
 static inline void *vport_priv(const struct vport *vport)
 {
-   return (u8 *)vport + ALIGN(sizeof(struct vport), VPORT_ALIGN);
+   return (u8 *)(uintptr_t)vport + ALIGN(sizeof(struct vport), 
VPORT_ALIGN);
 }
 
 /**
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 07/29] openvswitch: Use ether_addr_copy

2014-08-20 Thread zhe.he
From: Joe Perches j...@perches.com

commit 8c63ff09bddf944ab0033fea97aacfadfffa76de upstream

It's slightly smaller/faster for some architectures.

Signed-off-by: Joe Perches j...@perches.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/actions.c  |  4 ++--
 net/openvswitch/flow.c | 16 
 net/openvswitch/flow_netlink.c | 12 ++--
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 2c77e7b..c36856a 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -134,8 +134,8 @@ static int set_eth_addr(struct sk_buff *skb,
 
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
 
-   memcpy(eth_hdr(skb)-h_source, eth_key-eth_src, ETH_ALEN);
-   memcpy(eth_hdr(skb)-h_dest, eth_key-eth_dst, ETH_ALEN);
+   ether_addr_copy(eth_hdr(skb)-h_source, eth_key-eth_src);
+   ether_addr_copy(eth_hdr(skb)-h_dest, eth_key-eth_dst);
 
ovs_skb_postpush_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
 
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 2998989..332aa01 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -372,14 +372,14 @@ static int parse_icmpv6(struct sk_buff *skb, struct 
sw_flow_key *key,
 opt_len == 8) {
if 
(unlikely(!is_zero_ether_addr(key-ipv6.nd.sll)))
goto invalid;
-   memcpy(key-ipv6.nd.sll,
-   nd-opt[offset+sizeof(*nd_opt)], ETH_ALEN);
+   ether_addr_copy(key-ipv6.nd.sll,
+   
nd-opt[offset+sizeof(*nd_opt)]);
} else if (nd_opt-nd_opt_type == ND_OPT_TARGET_LL_ADDR
opt_len == 8) {
if 
(unlikely(!is_zero_ether_addr(key-ipv6.nd.tll)))
goto invalid;
-   memcpy(key-ipv6.nd.tll,
-   nd-opt[offset+sizeof(*nd_opt)], ETH_ALEN);
+   ether_addr_copy(key-ipv6.nd.tll,
+   
nd-opt[offset+sizeof(*nd_opt)]);
}
 
icmp_len -= opt_len;
@@ -439,8 +439,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, 
struct sw_flow_key *key)
 * header in the linear data area.
 */
eth = eth_hdr(skb);
-   memcpy(key-eth.src, eth-h_source, ETH_ALEN);
-   memcpy(key-eth.dst, eth-h_dest, ETH_ALEN);
+   ether_addr_copy(key-eth.src, eth-h_source);
+   ether_addr_copy(key-eth.dst, eth-h_dest);
 
__skb_pull(skb, 2 * ETH_ALEN);
/* We are going to push all headers that we pull, so no need to
@@ -538,8 +538,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, 
struct sw_flow_key *key)
key-ip.proto = ntohs(arp-ar_op);
memcpy(key-ipv4.addr.src, arp-ar_sip, 
sizeof(key-ipv4.addr.src));
memcpy(key-ipv4.addr.dst, arp-ar_tip, 
sizeof(key-ipv4.addr.dst));
-   memcpy(key-ipv4.arp.sha, arp-ar_sha, ETH_ALEN);
-   memcpy(key-ipv4.arp.tha, arp-ar_tha, ETH_ALEN);
+   ether_addr_copy(key-ipv4.arp.sha, arp-ar_sha);
+   ether_addr_copy(key-ipv4.arp.tha, arp-ar_tha);
}
} else if (key-eth.type == htons(ETH_P_IPV6)) {
int nh_len; /* IPv6 Header + Extensions */
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 7bd09b7..5511ad1 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -986,8 +986,8 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey,
goto nla_put_failure;
 
eth_key = nla_data(nla);
-   memcpy(eth_key-eth_src, output-eth.src, ETH_ALEN);
-   memcpy(eth_key-eth_dst, output-eth.dst, ETH_ALEN);
+   ether_addr_copy(eth_key-eth_src, output-eth.src);
+   ether_addr_copy(eth_key-eth_dst, output-eth.dst);
 
if (swkey-eth.tci || swkey-eth.type == htons(ETH_P_8021Q)) {
__be16 eth_type;
@@ -1059,8 +1059,8 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey,
arp_key-arp_sip = output-ipv4.addr.src;
arp_key-arp_tip = output-ipv4.addr.dst;
arp_key-arp_op = htons(output-ip.proto);
-   memcpy(arp_key-arp_sha, output-ipv4.arp.sha, ETH_ALEN);
-   memcpy(arp_key-arp_tha, output-ipv4.arp.tha, ETH_ALEN);
+   ether_addr_copy(arp_key-arp_sha, output-ipv4.arp.sha);
+   ether_addr_copy(arp_key-arp_tha, output-ipv4.arp.tha);
}
 
if ((swkey-eth.type == htons(ETH_P_IP) ||
@@ -1147,8 +1147,8 @@ 

[linux-yocto] [PATCH 05/29] openvswitch: Use net_ratelimit in OVS_NLERR

2014-08-20 Thread zhe.he
From: Joe Perches j...@perches.com

commit 1815a8831fb04c60d73627816cb0b596266e9bee upstream

Each use of pr_level_once has a per-site flag.

Some of the OVS_NLERR messages look as if seeing them
multiple times could be useful, so use net_ratelimit()
instead of pr_info_once.

Signed-off-by: Joe Perches j...@perches.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.h | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 6be9fbb..0f5e77c 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -194,7 +194,9 @@ struct sk_buff *ovs_vport_cmd_build_info(struct vport *, 
u32 pid, u32 seq,
 int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb);
 void ovs_dp_notify_wq(struct work_struct *work);
 
-#define OVS_NLERR(fmt, ...) \
-   pr_info_once(netlink:  fmt, ##__VA_ARGS__)
-
+#define OVS_NLERR(fmt, ...)\
+do {   \
+   if (net_ratelimit())\
+   pr_info(netlink:  fmt, ##__VA_ARGS__);\
+} while (0)
 #endif /* datapath.h */
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 08/29] openvswitch: Remove 5-tuple optimization.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 23dabf88abb48a866fdb19ee08ebcf1ddd9b1840 upstream

The 5-tuple optimization becomes unnecessary with a later per-NUMA
node stats patch.  Remove it first to make the changes easier to
grasp.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 11 
 net/openvswitch/flow.c | 32 +--
 net/openvswitch/flow.h | 10 +---
 net/openvswitch/flow_netlink.c | 58 +++---
 net/openvswitch/flow_netlink.h |  1 -
 net/openvswitch/flow_table.c   | 31 +++---
 net/openvswitch/flow_table.h   |  2 +-
 7 files changed, 32 insertions(+), 113 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 270b77d..23a713e 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -524,7 +524,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, 
struct genl_info *info)
packet-protocol = htons(ETH_P_802_2);
 
/* Build an sw_flow for sending this packet. */
-   flow = ovs_flow_alloc(false);
+   flow = ovs_flow_alloc();
err = PTR_ERR(flow);
if (IS_ERR(flow))
goto err_kfree_skb;
@@ -782,7 +782,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
struct datapath *dp;
struct sw_flow_actions *acts = NULL;
struct sw_flow_match match;
-   bool exact_5tuple;
int error;
 
/* Extract key. */
@@ -791,7 +790,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
goto error;
 
ovs_match_init(match, key, mask);
-   error = ovs_nla_get_match(match, exact_5tuple,
+   error = ovs_nla_get_match(match,
  a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]);
if (error)
goto error;
@@ -830,7 +829,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
goto err_unlock_ovs;
 
/* Allocate flow. */
-   flow = ovs_flow_alloc(!exact_5tuple);
+   flow = ovs_flow_alloc();
if (IS_ERR(flow)) {
error = PTR_ERR(flow);
goto err_unlock_ovs;
@@ -914,7 +913,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct 
genl_info *info)
}
 
ovs_match_init(match, key, NULL);
-   err = ovs_nla_get_match(match, NULL, a[OVS_FLOW_ATTR_KEY], NULL);
+   err = ovs_nla_get_match(match, a[OVS_FLOW_ATTR_KEY], NULL);
if (err)
return err;
 
@@ -968,7 +967,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct 
genl_info *info)
}
 
ovs_match_init(match, key, NULL);
-   err = ovs_nla_get_match(match, NULL, a[OVS_FLOW_ATTR_KEY], NULL);
+   err = ovs_nla_get_match(match, a[OVS_FLOW_ATTR_KEY], NULL);
if (err)
goto unlock;
 
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 332aa01..aad7a8d 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -66,10 +66,7 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct 
sk_buff *skb)
struct flow_stats *stats;
__be16 tcp_flags = 0;
 
-   if (!flow-stats.is_percpu)
-   stats = flow-stats.stat;
-   else
-   stats = this_cpu_ptr(flow-stats.cpu_stats);
+   stats = this_cpu_ptr(flow-stats);
 
if ((flow-key.eth.type == htons(ETH_P_IP) ||
 flow-key.eth.type == htons(ETH_P_IPV6)) 
@@ -110,16 +107,14 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct 
ovs_flow_stats *ovs_stats,
memset(ovs_stats, 0, sizeof(*ovs_stats));
 
local_bh_disable();
-   if (!flow-stats.is_percpu) {
-   stats_read(flow-stats.stat, ovs_stats, used, tcp_flags);
-   } else {
-   for_each_possible_cpu(cpu) {
-   struct flow_stats *stats;
-
-   stats = per_cpu_ptr(flow-stats.cpu_stats, cpu);
-   stats_read(stats, ovs_stats, used, tcp_flags);
-   }
+
+   for_each_possible_cpu(cpu) {
+   struct flow_stats *stats;
+
+   stats = per_cpu_ptr(flow-stats.cpu_stats, cpu);
+   stats_read(stats, ovs_stats, used, tcp_flags);
}
+
local_bh_enable();
 }
 
@@ -138,13 +133,10 @@ void ovs_flow_stats_clear(struct sw_flow *flow)
int cpu;
 
local_bh_disable();
-   if (!flow-stats.is_percpu) {
-   stats_reset(flow-stats.stat);
-   } else {
-   for_each_possible_cpu(cpu) {
-   stats_reset(per_cpu_ptr(flow-stats.cpu_stats, cpu));
-   }
-   }
+
+   for_each_possible_cpu(cpu)
+   

[linux-yocto] [PATCH 09/29] openvswitch: Per NUMA node flow stats.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 63e7959c4b9bd6f791061c460a22d9ee32ae2240 upstream

Keep kernel flow stats for each NUMA node rather than each (logical)
CPU.  This avoids using the per-CPU allocator and removes most of the
kernel-side OVS locking overhead otherwise on the top of perf reports
and allows OVS to scale better with higher number of threads.

With 9 handlers and 4 revalidators netperf TCP_CRR test flow setup
rate doubles on a server with two hyper-threaded physical CPUs (16
logical cores each) compared to the current OVS master.  Tested with
non-trivial flow table with a TCP port match rule forcing all new
connections with unique port numbers to OVS userspace.  The IP
addresses are still wildcarded, so the kernel flows are not considered
as exact match 5-tuple flows.  This type of flows can be expected to
appear in large numbers as the result of more effective wildcarding
made possible by improvements in OVS userspace flow classifier.

Perf results for this test (master):

Events: 305K cycles
+   8.43% ovs-vswitchd  [kernel.kallsyms]   [k] mutex_spin_on_owner
+   5.64% ovs-vswitchd  [kernel.kallsyms]   [k] __ticket_spin_lock
+   4.75% ovs-vswitchd  ovs-vswitchd[.] find_match_wc
+   3.32% ovs-vswitchd  libpthread-2.15.so  [.] pthread_mutex_lock
+   2.61% ovs-vswitchd  [kernel.kallsyms]   [k] pcpu_alloc_area
+   2.19% ovs-vswitchd  ovs-vswitchd[.] flow_hash_in_minimask_range
+   2.03%  swapper  [kernel.kallsyms]   [k] intel_idle
+   1.84% ovs-vswitchd  libpthread-2.15.so  [.] pthread_mutex_unlock
+   1.64% ovs-vswitchd  ovs-vswitchd[.] classifier_lookup
+   1.58% ovs-vswitchd  libc-2.15.so[.] 0x7f4e6
+   1.07% ovs-vswitchd  [kernel.kallsyms]   [k] memset
+   1.03%  netperf  [kernel.kallsyms]   [k] __ticket_spin_lock
+   0.92%  swapper  [kernel.kallsyms]   [k] __ticket_spin_lock
...

And after this patch:

Events: 356K cycles
+   6.85% ovs-vswitchd  ovs-vswitchd[.] find_match_wc
+   4.63% ovs-vswitchd  libpthread-2.15.so  [.] pthread_mutex_lock
+   3.06% ovs-vswitchd  [kernel.kallsyms]   [k] __ticket_spin_lock
+   2.81% ovs-vswitchd  ovs-vswitchd[.] flow_hash_in_minimask_range
+   2.51% ovs-vswitchd  libpthread-2.15.so  [.] pthread_mutex_unlock
+   2.27% ovs-vswitchd  ovs-vswitchd[.] classifier_lookup
+   1.84% ovs-vswitchd  libc-2.15.so[.] 0x15d30f
+   1.74% ovs-vswitchd  [kernel.kallsyms]   [k] mutex_spin_on_owner
+   1.47%  swapper  [kernel.kallsyms]   [k] intel_idle
+   1.34% ovs-vswitchd  ovs-vswitchd[.] flow_hash_in_minimask
+   1.33% ovs-vswitchd  ovs-vswitchd[.] rule_actions_unref
+   1.16% ovs-vswitchd  ovs-vswitchd[.] hindex_node_with_hash
+   1.16% ovs-vswitchd  ovs-vswitchd[.] do_xlate_actions
+   1.09% ovs-vswitchd  ovs-vswitchd[.] ofproto_rule_ref
+   1.01%  netperf  [kernel.kallsyms]   [k] __ticket_spin_lock
...

There is a small increase in kernel spinlock overhead due to the same
spinlock being shared between multiple cores of the same physical CPU,
but that is barely visible in the netperf TCP_CRR test performance
(maybe ~1% performance drop, hard to tell exactly due to variance in
the test results), when testing for kernel module throughput (with no
userspace activity, handful of kernel flows).

On flow setup, a single stats instance is allocated (for the NUMA node
0).  As CPUs from multiple NUMA nodes start updating stats, new
NUMA-node specific stats instances are allocated.  This allocation on
the packet processing code path is made to never block or look for
emergency memory pools, minimizing the allocation latency.  If the
allocation fails, the existing preallocated stats instance is used.
Also, if only CPUs from one NUMA-node are updating the preallocated
stats instance, no additional stats instances are allocated.  This
eliminates the need to pre-allocate stats instances that will not be
used, also relieving the stats reader from the burden of reading stats
that are never used.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Acked-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/flow.c   | 119 ---
 net/openvswitch/flow.h   |  10 +++-
 net/openvswitch/flow_table.c |  46 +
 net/openvswitch/flow_table.h |   2 +
 4 files changed, 122 insertions(+), 55 deletions(-)

diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index aad7a8d..432f04d 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -65,8 +65,9 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct 
sk_buff *skb)
 {
struct flow_stats *stats;
__be16 tcp_flags = 0;
+   int node = numa_node_id();
 
-   stats = this_cpu_ptr(flow-stats);
+   stats = 

[linux-yocto] [PATCH 11/29] openvswitch: Use TCP flags in the flow key for stats.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 88d73f6c411ac2f057829b93b3cf202ee551f6cb upstream

We already extract the TCP flags for the key, might as well use that
for stats.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Acked-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/flow.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 432f04d..e0fc12b 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -69,14 +69,12 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct 
sk_buff *skb)
 
stats = rcu_dereference(flow-stats[node]);
 
-   if ((flow-key.eth.type == htons(ETH_P_IP) ||
-flow-key.eth.type == htons(ETH_P_IPV6)) 
-   flow-key.ip.frag != OVS_FRAG_TYPE_LATER 
-   flow-key.ip.proto == IPPROTO_TCP 
-   likely(skb-len = skb_transport_offset(skb) + sizeof(struct 
tcphdr))) {
-   tcp_flags = TCP_FLAGS_BE16(tcp_hdr(skb));
+   if (likely(flow-key.ip.proto == IPPROTO_TCP)) {
+   if (likely(flow-key.eth.type == htons(ETH_P_IP)))
+   tcp_flags = flow-key.ipv4.tp.flags;
+   else if (likely(flow-key.eth.type == htons(ETH_P_IPV6)))
+   tcp_flags = flow-key.ipv6.tp.flags;
}
-
/* Check if already have node-specific stats. */
if (likely(stats)) {
spin_lock(stats-lock);
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 12/29] net/openvswitch: Use with RCU_INIT_POINTER(x, NULL) in vport-gre.c

2014-08-20 Thread zhe.he
From: Monam Agarwal monamagarwal...@gmail.com

commit 944df8ae84d88f5e8eb027990dad2cfa4fbe4be5 upstream

This patch replaces rcu_assign_pointer(x, NULL) with RCU_INIT_POINTER(x, NULL)

The rcu_assign_pointer() ensures that the initialization of a structure
is carried out before storing a pointer to that structure.
And in the case of the NULL pointer, there is no structure to initialize.
So, rcu_assign_pointer(p, NULL) can be safely converted to RCU_INIT_POINTER(p, 
NULL)

Signed-off-by: Monam Agarwal monamagarwal...@gmail.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/vport-gre.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index a3d6951..a0da2dd 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -256,7 +256,7 @@ static void gre_tnl_destroy(struct vport *vport)
 
ovs_net = net_generic(net, ovs_net_id);
 
-   rcu_assign_pointer(ovs_net-vport_net.gre_vport, NULL);
+   RCU_INIT_POINTER(ovs_net-vport_net.gre_vport, NULL);
ovs_vport_deferred_free(vport);
gre_exit();
 }
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 18/29] openvswitch: Minimize dp and vport critical sections.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 6093ae9abac18871afd0bbc5cf093dff53112fcb upstream

Move most memory allocations away from the ovs_mutex critical
sections.  vport allocations still happen while the lock is taken, as
changing that would require major refactoring. Also, vports are
created very rarely so it should not matter.

Change ovs_dp_cmd_get() now only takes the rcu_read_lock(), rather
than ovs_lock(), as nothing need to be changed.  This was done by
ovs_vport_cmd_get() already.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 218 +++--
 1 file changed, 110 insertions(+), 108 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 1e928e3..b43b36c 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1164,23 +1164,9 @@ error:
return -EMSGSIZE;
 }
 
-/* Must be called with ovs_mutex. */
-static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp,
-struct genl_info *info, u8 cmd)
+static struct sk_buff *ovs_dp_cmd_alloc_info(struct genl_info *info)
 {
-   struct sk_buff *skb;
-   int retval;
-
-   skb = genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL);
-   if (!skb)
-   return ERR_PTR(-ENOMEM);
-
-   retval = ovs_dp_cmd_fill_info(dp, skb, info-snd_portid, info-snd_seq, 
0, cmd);
-   if (retval  0) {
-   kfree_skb(skb);
-   return ERR_PTR(retval);
-   }
-   return skb;
+   return genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL);
 }
 
 /* Called with rcu_read_lock or ovs_mutex. */
@@ -1233,12 +1219,14 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID])
goto err;
 
-   ovs_lock();
+   reply = ovs_dp_cmd_alloc_info(info);
+   if (!reply)
+   return -ENOMEM;
 
err = -ENOMEM;
dp = kzalloc(sizeof(*dp), GFP_KERNEL);
if (dp == NULL)
-   goto err_unlock_ovs;
+   goto err_free_reply;
 
ovs_dp_set_net(dp, hold_net(sock_net(skb-sk)));
 
@@ -1279,6 +1267,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
 
ovs_dp_change(dp, a);
 
+   /* So far only local changes have been made, now need the lock. */
+   ovs_lock();
+
vport = new_vport(parms);
if (IS_ERR(vport)) {
err = PTR_ERR(vport);
@@ -1297,10 +1288,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
goto err_destroy_ports_array;
}
 
-   reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW);
-   err = PTR_ERR(reply);
-   if (IS_ERR(reply))
-   goto err_destroy_local_port;
+   err = ovs_dp_cmd_fill_info(dp, reply, info-snd_portid,
+  info-snd_seq, 0, OVS_DP_CMD_NEW);
+   BUG_ON(err  0);
 
ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id);
list_add_tail_rcu(dp-list_node, ovs_net-dps);
@@ -1310,9 +1300,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
ovs_notify(dp_datapath_genl_family, reply, info);
return 0;
 
-err_destroy_local_port:
-   ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL));
 err_destroy_ports_array:
+   ovs_unlock();
kfree(dp-ports);
 err_destroy_percpu:
free_percpu(dp-stats_percpu);
@@ -1321,8 +1310,8 @@ err_destroy_table:
 err_free_dp:
release_net(ovs_dp_get_net(dp));
kfree(dp);
-err_unlock_ovs:
-   ovs_unlock();
+err_free_reply:
+   kfree_skb(reply);
 err:
return err;
 }
@@ -1360,16 +1349,19 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct 
genl_info *info)
struct datapath *dp;
int err;
 
+   reply = ovs_dp_cmd_alloc_info(info);
+   if (!reply)
+   return -ENOMEM;
+
ovs_lock();
dp = lookup_datapath(sock_net(skb-sk), info-userhdr, info-attrs);
err = PTR_ERR(dp);
if (IS_ERR(dp))
-   goto unlock;
+   goto err_unlock_free;
 
-   reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_DEL);
-   err = PTR_ERR(reply);
-   if (IS_ERR(reply))
-   goto unlock;
+   err = ovs_dp_cmd_fill_info(dp, reply, info-snd_portid,
+  info-snd_seq, 0, OVS_DP_CMD_DEL);
+   BUG_ON(err  0);
 
__dp_destroy(dp);
ovs_unlock();
@@ -1377,8 +1369,10 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct 
genl_info *info)
ovs_notify(dp_datapath_genl_family, reply, info);
 
return 0;
-unlock:
+
+err_unlock_free:
ovs_unlock();
+   kfree_skb(reply);
return err;
 }
 
@@ -1388,29 +1382,30 @@ static 

[linux-yocto] [PATCH 16/29] openvswitch: Build flow cmd netlink reply only if needed.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit fb5d1e9e127ad1542e5db20cd8620a1509baef69 upstream

Use netlink_has_listeners() and NLM_F_ECHO flag to determine if a
reply is needed or not for OVS_FLOW_CMD_NEW, OVS_FLOW_CMD_SET, or
OVS_FLOW_CMD_DEL.  Currently, OVS userspace does not request a reply
for OVS_FLOW_CMD_NEW, but usually does for OVS_FLOW_CMD_DEL, as stats
may have changed.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 70 +++---
 1 file changed, 48 insertions(+), 22 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 29409c8..1e928e3 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -62,6 +62,15 @@
 
 int ovs_net_id __read_mostly;
 
+/* Check if need to build a reply message.
+ * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
+static bool ovs_must_notify(struct genl_info *info,
+   const struct genl_multicast_group *grp)
+{
+   return info-nlhdr-nlmsg_flags  NLM_F_ECHO ||
+   netlink_has_listeners(genl_info_net(info)-genl_sock, 0);
+}
+
 static void ovs_notify(struct genl_family *family,
   struct sk_buff *skb, struct genl_info *info)
 {
@@ -746,27 +755,36 @@ error:
 
 /* Must be called with ovs_mutex. */
 static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow,
-  struct genl_info *info)
+  struct genl_info *info,
+  bool always)
 {
+   struct sk_buff *skb;
size_t len;
 
+   if (!always  !ovs_must_notify(info, ovs_dp_flow_multicast_group))
+   return NULL;
+
len = ovs_flow_cmd_msg_size(ovsl_dereference(flow-sf_acts));
 
-   return genlmsg_new_unicast(len, info, GFP_KERNEL);
+   skb = genlmsg_new_unicast(len, info, GFP_KERNEL);
+   if (!skb)
+   return ERR_PTR(-ENOMEM);
+
+   return skb;
 }
 
 /* Must be called with ovs_mutex. */
 static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow,
   struct datapath *dp,
   struct genl_info *info,
-  u8 cmd)
+  u8 cmd, bool always)
 {
struct sk_buff *skb;
int retval;
 
-   skb = ovs_flow_cmd_alloc_info(flow, info);
-   if (!skb)
-   return ERR_PTR(-ENOMEM);
+   skb = ovs_flow_cmd_alloc_info(flow, info, always);
+   if (!skb || IS_ERR(skb))
+   return skb;
 
retval = ovs_flow_cmd_fill_info(flow, dp, skb, info-snd_portid,
info-snd_seq, 0, cmd);
@@ -850,7 +868,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
goto err_flow_free;
}
 
-   reply = ovs_flow_cmd_build_info(flow, dp, info, 
OVS_FLOW_CMD_NEW);
+   reply = ovs_flow_cmd_build_info(flow, dp, info,
+   OVS_FLOW_CMD_NEW, false);
} else {
/* We found a matching flow. */
/* Bail out if we're not allowed to modify an existing flow.
@@ -876,7 +895,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
rcu_assign_pointer(flow-sf_acts, acts);
ovs_nla_free_flow_actions(old_acts);
}
-   reply = ovs_flow_cmd_build_info(flow, dp, info, 
OVS_FLOW_CMD_NEW);
+   reply = ovs_flow_cmd_build_info(flow, dp, info,
+   OVS_FLOW_CMD_NEW, false);
 
/* Clear stats. */
if (a[OVS_FLOW_ATTR_CLEAR])
@@ -884,11 +904,14 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
}
ovs_unlock();
 
-   if (!IS_ERR(reply))
-   ovs_notify(dp_flow_genl_family, reply, info);
-   else
-   genl_set_err(dp_flow_genl_family, sock_net(skb-sk), 0,
-0, PTR_ERR(reply));
+   if (reply) {
+   if (!IS_ERR(reply))
+   ovs_notify(dp_flow_genl_family, reply, info);
+   else
+   genl_set_err(dp_flow_genl_family, sock_net(skb-sk), 0,
+0, PTR_ERR(reply));
+   }
+
return 0;
 
 err_flow_free:
@@ -935,7 +958,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct 
genl_info *info)
goto unlock;
}
 
-   reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
+   reply = ovs_flow_cmd_build_info(flow, dp, info, 

[linux-yocto] [PATCH 17/29] openvswitch: Make flow mask removal symmetric.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 56c19868e115fcf8d62d843e1b9616bb9837d0db upstream

Masks are inserted when flows are inserted to the table, so it is
logical to correspondingly remove masks when flows are removed from
the table, in ovs_flow_table_remove().

This allows ovs_flow_free() to be called without locking, which will
be used by later patches.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/flow_table.c | 44 +---
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index d8ef37b..c80df6f 100644
--- a/net/openvswitch/flow_table.c
+++ b/net/openvswitch/flow_table.c
@@ -159,25 +159,6 @@ void ovs_flow_free(struct sw_flow *flow, bool deferred)
if (!flow)
return;
 
-   if (flow-mask) {
-   struct sw_flow_mask *mask = flow-mask;
-
-   /* ovs-lock is required to protect mask-refcount and
-* mask list.
-*/
-   ASSERT_OVSL();
-   BUG_ON(!mask-ref_count);
-   mask-ref_count--;
-
-   if (!mask-ref_count) {
-   list_del_rcu(mask-list);
-   if (deferred)
-   kfree_rcu(mask, rcu);
-   else
-   kfree(mask);
-   }
-   }
-
if (deferred)
call_rcu(flow-rcu, rcu_free_flow_callback);
else
@@ -491,6 +472,25 @@ static struct table_instance *table_instance_expand(struct 
table_instance *ti)
return table_instance_rehash(ti, ti-n_buckets * 2);
 }
 
+/* Remove 'mask' from the mask list, if it is not needed any more. */
+static void flow_mask_remove(struct flow_table *tbl, struct sw_flow_mask *mask)
+{
+   if (mask) {
+   /* ovs-lock is required to protect mask-refcount and
+* mask list.
+*/
+   ASSERT_OVSL();
+   BUG_ON(!mask-ref_count);
+   mask-ref_count--;
+
+   if (!mask-ref_count) {
+   list_del_rcu(mask-list);
+   kfree_rcu(mask, rcu);
+   }
+   }
+}
+
+/* Must be called with OVS mutex held. */
 void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
 {
struct table_instance *ti = ovsl_dereference(table-ti);
@@ -498,6 +498,11 @@ void ovs_flow_tbl_remove(struct flow_table *table, struct 
sw_flow *flow)
BUG_ON(table-count == 0);
hlist_del_rcu(flow-hash_node[ti-node_ver]);
table-count--;
+
+   /* RCU delete the mask. 'flow-mask' is not NULLed, as it should be
+* accessible as long as the RCU read lock is held.
+*/
+   flow_mask_remove(table, flow-mask);
 }
 
 static struct sw_flow_mask *mask_alloc(void)
@@ -560,6 +565,7 @@ static int flow_mask_insert(struct flow_table *tbl, struct 
sw_flow *flow,
return 0;
 }
 
+/* Must be called with OVS mutex held. */
 int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
struct sw_flow_mask *mask)
 {
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 15/29] openvswitch: Clarify locking.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit bb6f9a708d4067713afae2e9eb2637f6b4c01ecb upstream

Remove unnecessary locking from functions that are always called with
appropriate locking.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Thomas Graf tg...@redhat.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 13 +++--
 net/openvswitch/flow.c |  3 ++-
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index b4e58de..29409c8 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -173,6 +173,7 @@ static struct hlist_head *vport_hash_bucket(const struct 
datapath *dp,
return dp-ports[port_no  (DP_VPORT_HASH_BUCKETS - 1)];
 }
 
+/* Called with ovs_mutex or RCU read lock. */
 struct vport *ovs_lookup_vport(const struct datapath *dp, u16 port_no)
 {
struct vport *vport;
@@ -652,7 +653,7 @@ static size_t ovs_flow_cmd_msg_size(const struct 
sw_flow_actions *acts)
+ nla_total_size(acts-actions_len); /* OVS_FLOW_ATTR_ACTIONS */
 }
 
-/* Called with ovs_mutex. */
+/* Called with ovs_mutex or RCU read lock. */
 static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
  struct sk_buff *skb, u32 portid,
  u32 seq, u32 flags, u8 cmd)
@@ -743,6 +744,7 @@ error:
return err;
 }
 
+/* Must be called with ovs_mutex. */
 static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow,
   struct genl_info *info)
 {
@@ -753,6 +755,7 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(struct 
sw_flow *flow,
return genlmsg_new_unicast(len, info, GFP_KERNEL);
 }
 
+/* Must be called with ovs_mutex. */
 static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow,
   struct datapath *dp,
   struct genl_info *info,
@@ -1094,6 +1097,7 @@ static size_t ovs_dp_cmd_msg_size(void)
return msgsize;
 }
 
+/* Called with ovs_mutex or RCU read lock. */
 static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
u32 portid, u32 seq, u32 flags, u8 cmd)
 {
@@ -1109,9 +1113,7 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, 
struct sk_buff *skb,
 
ovs_header-dp_ifindex = get_dpifindex(dp);
 
-   rcu_read_lock();
err = nla_put_string(skb, OVS_DP_ATTR_NAME, ovs_dp_name(dp));
-   rcu_read_unlock();
if (err)
goto nla_put_failure;
 
@@ -1136,6 +1138,7 @@ error:
return -EMSGSIZE;
 }
 
+/* Must be called with ovs_mutex. */
 static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp,
 struct genl_info *info, u8 cmd)
 {
@@ -1154,7 +1157,7 @@ static struct sk_buff *ovs_dp_cmd_build_info(struct 
datapath *dp,
return skb;
 }
 
-/* Called with ovs_mutex. */
+/* Called with rcu_read_lock or ovs_mutex. */
 static struct datapath *lookup_datapath(struct net *net,
struct ovs_header *ovs_header,
struct nlattr *a[OVS_DP_ATTR_MAX + 1])
@@ -1166,10 +1169,8 @@ static struct datapath *lookup_datapath(struct net *net,
else {
struct vport *vport;
 
-   rcu_read_lock();
vport = ovs_vport_locate(net, nla_data(a[OVS_DP_ATTR_NAME]));
dp = vport  vport-port_no == OVSP_LOCAL ? vport-dp : NULL;
-   rcu_read_unlock();
}
return dp ? dp : ERR_PTR(-ENODEV);
 }
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 6d8d2da..1019fc1 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -122,6 +122,7 @@ unlock:
spin_unlock(stats-lock);
 }
 
+/* Called with ovs_mutex. */
 void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats,
unsigned long *used, __be16 *tcp_flags)
 {
@@ -132,7 +133,7 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct 
ovs_flow_stats *ovs_stats,
memset(ovs_stats, 0, sizeof(*ovs_stats));
 
for_each_node(node) {
-   struct flow_stats *stats = rcu_dereference(flow-stats[node]);
+   struct flow_stats *stats = ovsl_dereference(flow-stats[node]);
 
if (stats) {
/* Local CPU may write on non-local stats, so we must
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 14/29] openvswitch: Avoid assigning a NULL pointer to flow actions.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit be52c9e96a6657d117bb0ec6e11438fb246af5c7 upstream

Flow SET can accept an empty set of actions, with the intended
semantics of leaving existing actions unmodified.  This seems to have
been brokin after OVS 1.7, as we have assigned the flow's actions
pointer to NULL in this case, but we never check for the NULL pointer
later on.  This patch restores the intended behavior and documents it
in the include/linux/openvswitch.h.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 include/uapi/linux/openvswitch.h |  4 +++-
 net/openvswitch/datapath.c   | 14 --
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 970553c..0b979ee 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -395,7 +395,9 @@ struct ovs_key_nd {
  * @OVS_FLOW_ATTR_ACTIONS: Nested %OVS_ACTION_ATTR_* attributes specifying
  * the actions to take for packets that match the key.  Always present in
  * notifications.  Required for %OVS_FLOW_CMD_NEW requests, optional for
- * %OVS_FLOW_CMD_SET requests.
+ * %OVS_FLOW_CMD_SET requests.  An %OVS_FLOW_CMD_SET without
+ * %OVS_FLOW_ATTR_ACTIONS will not modify the actions.  To clear the actions,
+ * an %OVS_FLOW_ATTR_ACTIONS without any nested attributes must be given.
  * @OVS_FLOW_ATTR_STATS: struct ovs_flow_stats giving statistics for this
  * flow.  Present in notifications if the stats would be nonzero.  Ignored in
  * requests.
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 23a713e..b4e58de 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -810,6 +810,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
goto err_kfree;
}
} else if (info-genlhdr-cmd == OVS_FLOW_CMD_NEW) {
+   /* OVS_FLOW_CMD_NEW must have actions. */
error = -EINVAL;
goto error;
}
@@ -849,8 +850,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
reply = ovs_flow_cmd_build_info(flow, dp, info, 
OVS_FLOW_CMD_NEW);
} else {
/* We found a matching flow. */
-   struct sw_flow_actions *old_acts;
-
/* Bail out if we're not allowed to modify an existing flow.
 * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
 * because Generic Netlink treats the latter as a dump
@@ -866,11 +865,14 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
if (!ovs_flow_cmp_unmasked_key(flow, match))
goto err_unlock_ovs;
 
-   /* Update actions. */
-   old_acts = ovsl_dereference(flow-sf_acts);
-   rcu_assign_pointer(flow-sf_acts, acts);
-   ovs_nla_free_flow_actions(old_acts);
+   /* Update actions, if present. */
+   if (acts) {
+   struct sw_flow_actions *old_acts;
 
+   old_acts = ovsl_dereference(flow-sf_acts);
+   rcu_assign_pointer(flow-sf_acts, acts);
+   ovs_nla_free_flow_actions(old_acts);
+   }
reply = ovs_flow_cmd_build_info(flow, dp, info, 
OVS_FLOW_CMD_NEW);
 
/* Clear stats. */
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 13/29] openvswitch: Compact sw_flow_key.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 1139e241ec436b9e9610c7a33ac5c6657f87fda1 upstream

Minimize padding in sw_flow_key and move 'tp' top the main struct.
These changes simplify code when accessing the transport port numbers
and the tcp flags, and makes the sw_flow_key 8 bytes smaller on 64-bit
systems (128-120 bytes).  These changes also make the keys for IPv4
packets to fit in one cache line.

There is a valid concern for safety of packing the struct
ovs_key_ipv4_tunnel, as it would be possible to take the address of
the tun_id member as a __be64 * which could result in unaligned access
in some systems. However:

- sw_flow_key itself is 64-bit aligned, so the tun_id within is
  always
  64-bit aligned.
- We never make arrays of ovs_key_ipv4_tunnel (which would force
  every
  second tun_key to be misaligned).
- We never take the address of the tun_id in to a __be64 *.
- Whereever we use struct ovs_key_ipv4_tunnel outside the
  sw_flow_key,
  it is in stack (on tunnel input functions), where compiler has full
  control of the alignment.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/flow.c |  44 +++-
 net/openvswitch/flow.h |  29 ---
 net/openvswitch/flow_netlink.c | 112 -
 3 files changed, 62 insertions(+), 123 deletions(-)

diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index e0fc12b..6d8d2da 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -64,17 +64,11 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
 void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
 {
struct flow_stats *stats;
-   __be16 tcp_flags = 0;
+   __be16 tcp_flags = flow-key.tp.flags;
int node = numa_node_id();
 
stats = rcu_dereference(flow-stats[node]);
 
-   if (likely(flow-key.ip.proto == IPPROTO_TCP)) {
-   if (likely(flow-key.eth.type == htons(ETH_P_IP)))
-   tcp_flags = flow-key.ipv4.tp.flags;
-   else if (likely(flow-key.eth.type == htons(ETH_P_IPV6)))
-   tcp_flags = flow-key.ipv6.tp.flags;
-   }
/* Check if already have node-specific stats. */
if (likely(stats)) {
spin_lock(stats-lock);
@@ -357,8 +351,8 @@ static int parse_icmpv6(struct sk_buff *skb, struct 
sw_flow_key *key,
/* The ICMPv6 type and code fields use the 16-bit transport port
 * fields, so we need to store them in 16-bit network byte order.
 */
-   key-ipv6.tp.src = htons(icmp-icmp6_type);
-   key-ipv6.tp.dst = htons(icmp-icmp6_code);
+   key-tp.src = htons(icmp-icmp6_type);
+   key-tp.dst = htons(icmp-icmp6_code);
 
if (icmp-icmp6_code == 0 
(icmp-icmp6_type == NDISC_NEIGHBOUR_SOLICITATION ||
@@ -520,21 +514,21 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, 
struct sw_flow_key *key)
if (key-ip.proto == IPPROTO_TCP) {
if (tcphdr_ok(skb)) {
struct tcphdr *tcp = tcp_hdr(skb);
-   key-ipv4.tp.src = tcp-source;
-   key-ipv4.tp.dst = tcp-dest;
-   key-ipv4.tp.flags = TCP_FLAGS_BE16(tcp);
+   key-tp.src = tcp-source;
+   key-tp.dst = tcp-dest;
+   key-tp.flags = TCP_FLAGS_BE16(tcp);
}
} else if (key-ip.proto == IPPROTO_UDP) {
if (udphdr_ok(skb)) {
struct udphdr *udp = udp_hdr(skb);
-   key-ipv4.tp.src = udp-source;
-   key-ipv4.tp.dst = udp-dest;
+   key-tp.src = udp-source;
+   key-tp.dst = udp-dest;
}
} else if (key-ip.proto == IPPROTO_SCTP) {
if (sctphdr_ok(skb)) {
struct sctphdr *sctp = sctp_hdr(skb);
-   key-ipv4.tp.src = sctp-source;
-   key-ipv4.tp.dst = sctp-dest;
+   key-tp.src = sctp-source;
+   key-tp.dst = sctp-dest;
}
} else if (key-ip.proto == IPPROTO_ICMP) {
if (icmphdr_ok(skb)) {
@@ -542,8 +536,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, 
struct sw_flow_key *key)
/* The ICMP type and code fields use the 16-bit
 * transport port fields, so we need to store
 * them in 16-bit network byte order. */
-   key-ipv4.tp.src = htons(icmp-type);
-  

[linux-yocto] [PATCH 19/29] openvswitch: Fix typo.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit eb07265904d6ee95497aba0f3cbd2ae6d9c39a97 upstream

Incorrect struct name was confusing, even though otherwise
inconsequental.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/flow_table.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index c80df6f..574c3ab 100644
--- a/net/openvswitch/flow_table.c
+++ b/net/openvswitch/flow_table.c
@@ -139,7 +139,7 @@ static void flow_free(struct sw_flow *flow)
 {
int node;
 
-   kfree((struct sf_flow_acts __force *)flow-sf_acts);
+   kfree((struct sw_flow_actions __force *)flow-sf_acts);
for_each_node(node)
if (flow-stats[node])
kmem_cache_free(flow_stats_cache,
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 28/29] openvswitch: Fix tracking of flags seen in TCP flows.

2014-08-20 Thread zhe.he
From: Ben Pfaff b...@nicira.com

commit ad55200734c65a3ec5d0c39d6ea904008baea536 upstream

Flow statistics need to take into account the TCP flags from the packet
currently being processed (in 'key'), not the TCP flags matched by the
flow found in the kernel flow table (in 'flow').

This bug made the Open vSwitch userspace fin_timeout action have no effect
in many cases.
This bug is introduced by commit 88d73f6c411ac2f0578 (openvswitch: Use
TCP flags in the flow key for stats.)

Reported-by: Len Gao l...@vmware.com
Signed-off-by: Ben Pfaff b...@nicira.com
Acked-by: Jarno Rajahalme jrajaha...@nicira.com
Acked-by: Jesse Gross je...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 4 ++--
 net/openvswitch/flow.c | 4 ++--
 net/openvswitch/flow.h | 5 +++--
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 7ef8d3f..4c5d49d 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2013 Nicira, Inc.
+ * Copyright (c) 2007-2014 Nicira, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
@@ -276,7 +276,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct 
sk_buff *skb)
OVS_CB(skb)-flow = flow;
OVS_CB(skb)-pkt_key = key;
 
-   ovs_flow_stats_update(OVS_CB(skb)-flow, skb);
+   ovs_flow_stats_update(OVS_CB(skb)-flow, key.tp.flags, skb);
ovs_execute_actions(dp, skb);
stats_counter = stats-n_hit;
 
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 334751c..d07ab53 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -61,10 +61,10 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies)
 
 #define TCP_FLAGS_BE16(tp) (*(__be16 *)tcp_flag_word(tp)  htons(0x0FFF))
 
-void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb)
+void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
+  struct sk_buff *skb)
 {
struct flow_stats *stats;
-   __be16 tcp_flags = flow-key.tp.flags;
int node = numa_node_id();
 
stats = rcu_dereference(flow-stats[node]);
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index ac395d2..5e5aaed 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2013 Nicira, Inc.
+ * Copyright (c) 2007-2014 Nicira, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
@@ -180,7 +180,8 @@ struct arp_eth_header {
unsigned char   ar_tip[4];  /* target IP address*/
 } __packed;
 
-void ovs_flow_stats_update(struct sw_flow *, struct sk_buff *);
+void ovs_flow_stats_update(struct sw_flow *, __be16 tcp_flags,
+  struct sk_buff *);
 void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
unsigned long *used, __be16 *tcp_flags);
 void ovs_flow_stats_clear(struct sw_flow *);
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 21/29] openvswitch: Reduce locking requirements.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 0e9796b4af9ef490e203158cb738a5a4986eb75c upstream

Reduce and clarify locking requirements for ovs_flow_cmd_alloc_info(),
ovs_flow_cmd_fill_info() and ovs_flow_cmd_build_info().

A datapath pointer is available only when holding a lock.  Change
ovs_flow_cmd_fill_info() and ovs_flow_cmd_build_info() to take a
dp_ifindex directly, rather than a datapath pointer that is then
(only) used to get the dp_ifindex.  This is useful, since the
dp_ifindex is available even when the datapath pointer is not, both
before and after taking a lock, which makes further critical section
reduction possible.

Make ovs_flow_cmd_alloc_info() take an 'acts' argument instead a
'flow' pointer.  This allows some future patches to do the allocation
before acquiring the flow pointer.

The locking requirements after this patch are:

ovs_flow_cmd_alloc_info(): May be called without locking, must not be
called while holding the RCU read lock (due to memory allocation).
If 'acts' belong to a flow in the flow table, however, then the
caller must hold ovs_mutex.

ovs_flow_cmd_fill_info(): Either ovs_mutex or RCU read lock must be held.

ovs_flow_cmd_build_info(): This calls both of the above, so the caller
must hold ovs_mutex.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 54 +-
 1 file changed, 29 insertions(+), 25 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index b43b36c..91b4286 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -663,7 +663,7 @@ static size_t ovs_flow_cmd_msg_size(const struct 
sw_flow_actions *acts)
 }
 
 /* Called with ovs_mutex or RCU read lock. */
-static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
+static int ovs_flow_cmd_fill_info(const struct sw_flow *flow, int dp_ifindex,
  struct sk_buff *skb, u32 portid,
  u32 seq, u32 flags, u8 cmd)
 {
@@ -680,7 +680,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, 
struct datapath *dp,
if (!ovs_header)
return -EMSGSIZE;
 
-   ovs_header-dp_ifindex = get_dpifindex(dp);
+   ovs_header-dp_ifindex = dp_ifindex;
 
/* Fill flow key. */
nla = nla_nest_start(skb, OVS_FLOW_ATTR_KEY);
@@ -703,6 +703,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, 
struct datapath *dp,
nla_nest_end(skb, nla);
 
ovs_flow_stats_get(flow, stats, used, tcp_flags);
+
if (used 
nla_put_u64(skb, OVS_FLOW_ATTR_USED, ovs_flow_used_time(used)))
goto nla_put_failure;
@@ -730,9 +731,9 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, 
struct datapath *dp,
const struct sw_flow_actions *sf_acts;
 
sf_acts = rcu_dereference_ovsl(flow-sf_acts);
-
err = ovs_nla_put_actions(sf_acts-actions,
  sf_acts-actions_len, skb);
+
if (!err)
nla_nest_end(skb, start);
else {
@@ -753,41 +754,40 @@ error:
return err;
 }
 
-/* Must be called with ovs_mutex. */
-static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow,
+/* May not be called with RCU read lock. */
+static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow_actions 
*acts,
   struct genl_info *info,
   bool always)
 {
struct sk_buff *skb;
-   size_t len;
 
if (!always  !ovs_must_notify(info, ovs_dp_flow_multicast_group))
return NULL;
 
-   len = ovs_flow_cmd_msg_size(ovsl_dereference(flow-sf_acts));
-
-   skb = genlmsg_new_unicast(len, info, GFP_KERNEL);
+   skb = genlmsg_new_unicast(ovs_flow_cmd_msg_size(acts), info, 
GFP_KERNEL);
if (!skb)
return ERR_PTR(-ENOMEM);
 
return skb;
 }
 
-/* Must be called with ovs_mutex. */
-static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow,
-  struct datapath *dp,
-  struct genl_info *info,
-  u8 cmd, bool always)
+/* Called with ovs_mutex. */
+static struct sk_buff *ovs_flow_cmd_build_info(const struct sw_flow *flow,
+  int dp_ifindex,
+  struct genl_info *info, u8 cmd,
+  bool always)
 {
struct sk_buff *skb;
int retval;
 
-   skb = ovs_flow_cmd_alloc_info(flow, info, always);
+   skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow-sf_acts), info,
+ always);

[linux-yocto] [PATCH 23/29] openvswitch: Split ovs_flow_cmd_new_or_set().

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 37bdc87ba00dadd0156db77ba48224d042202435 upstream

Following patch will be easier to reason about with separate
ovs_flow_cmd_new() and ovs_flow_cmd_set() functions.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 160 -
 1 file changed, 116 insertions(+), 44 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index f9e6797..ce7fe6d 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -792,16 +792,16 @@ static struct sk_buff *ovs_flow_cmd_build_info(const 
struct sw_flow *flow,
return skb;
 }
 
-static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
+static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
 {
struct nlattr **a = info-attrs;
struct ovs_header *ovs_header = info-userhdr;
struct sw_flow_key key, masked_key;
-   struct sw_flow *flow = NULL;
+   struct sw_flow *flow;
struct sw_flow_mask mask;
struct sk_buff *reply;
struct datapath *dp;
-   struct sw_flow_actions *acts = NULL;
+   struct sw_flow_actions *acts;
struct sw_flow_match match;
int error;
 
@@ -817,23 +817,21 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
goto error;
 
/* Validate actions. */
-   if (a[OVS_FLOW_ATTR_ACTIONS]) {
-   acts = 
ovs_nla_alloc_flow_actions(nla_len(a[OVS_FLOW_ATTR_ACTIONS]));
-   error = PTR_ERR(acts);
-   if (IS_ERR(acts))
-   goto error;
+   error = -EINVAL;
+   if (!a[OVS_FLOW_ATTR_ACTIONS])
+   goto error;
 
-   ovs_flow_mask_key(masked_key, key, mask);
-   error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS],
-masked_key, 0, acts);
-   if (error) {
-   OVS_NLERR(Flow actions may not be safe on all matching 
packets.\n);
-   goto err_kfree;
-   }
-   } else if (info-genlhdr-cmd == OVS_FLOW_CMD_NEW) {
-   /* OVS_FLOW_CMD_NEW must have actions. */
-   error = -EINVAL;
+   acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_FLOW_ATTR_ACTIONS]));
+   error = PTR_ERR(acts);
+   if (IS_ERR(acts))
goto error;
+
+   ovs_flow_mask_key(masked_key, key, mask);
+   error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS],
+masked_key, 0, acts);
+   if (error) {
+   OVS_NLERR(Flow actions may not be safe on all matching 
packets.\n);
+   goto err_kfree;
}
 
ovs_lock();
@@ -845,11 +843,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
/* Check if this is a duplicate flow */
flow = ovs_flow_tbl_lookup(dp-table, key);
if (!flow) {
-   /* Bail out if we're not allowed to create a new flow. */
-   error = -ENOENT;
-   if (info-genlhdr-cmd == OVS_FLOW_CMD_SET)
-   goto err_unlock_ovs;
-
/* Allocate flow. */
flow = ovs_flow_alloc();
if (IS_ERR(flow)) {
@@ -867,11 +860,9 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
acts = NULL;
goto err_flow_free;
}
-
-   reply = ovs_flow_cmd_build_info(flow, ovs_header-dp_ifindex,
-   info, OVS_FLOW_CMD_NEW, false);
} else {
-   /* We found a matching flow. */
+   struct sw_flow_actions *old_acts;
+
/* Bail out if we're not allowed to modify an existing flow.
 * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
 * because Generic Netlink treats the latter as a dump
@@ -879,30 +870,113 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
 * gets fixed.
 */
error = -EEXIST;
-   if (info-genlhdr-cmd == OVS_FLOW_CMD_NEW 
-   info-nlhdr-nlmsg_flags  (NLM_F_CREATE | NLM_F_EXCL))
+   if (info-nlhdr-nlmsg_flags  (NLM_F_CREATE | NLM_F_EXCL))
goto err_unlock_ovs;
 
/* The unmasked key has to be the same for flow updates. */
if (!ovs_flow_cmp_unmasked_key(flow, match))
goto err_unlock_ovs;
 
-   /* Update actions, if present. */
-   if (acts) {
-   struct sw_flow_actions *old_acts;
+   /* Update actions. */
+   old_acts = 

[linux-yocto] [PATCH 26/29] openvswitch: Fix a double free bug for the sample action

2014-08-20 Thread zhe.he
From: Andy Zhou az...@nicira.com

commit fe984c08e20f0fc2b4666bf8eeeb02605568387b upstream

When sample action returns with an error, the skb has already been
freed. This patch fix a bug to make sure we don't free it again.
This bug introduced by commit ccb1352e76cff05 (net: Add Open vSwitch
kernel components.)

Signed-off-by: Andy Zhou az...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/actions.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index c36856a..e70d8b1 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -551,6 +551,8 @@ static int do_execute_actions(struct datapath *dp, struct 
sk_buff *skb,
 
case OVS_ACTION_ATTR_SAMPLE:
err = sample(dp, skb, a);
+   if (unlikely(err)) /* skb already freed. */
+   return err;
break;
}
 
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 25/29] openvswitch: Simplify genetlink code.

2014-08-20 Thread zhe.he
From: Pravin B Shelar pshe...@nicira.com

commit 0c200ef94c9492205e18a18c25650cf27939889c upstream

Following patch get rid of struct genl_family_and_ops which is
redundant due to changes to struct genl_family.

Signed-off-by: Kyle Mestery mest...@noironetworks.com
Acked-by: Kyle Mestery mest...@noironetworks.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 185 ++---
 1 file changed, 90 insertions(+), 95 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index aedbd1d..7ef8d3f 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -44,11 +44,11 @@
 #include linux/netfilter_ipv4.h
 #include linux/inetdevice.h
 #include linux/list.h
-#include linux/lockdep.h
 #include linux/openvswitch.h
 #include linux/rculist.h
 #include linux/dmi.h
-#include linux/workqueue.h
+#include linux/genetlink.h
+#include net/genetlink.h
 #include net/genetlink.h
 #include net/net_namespace.h
 #include net/netns/generic.h
@@ -62,6 +62,22 @@
 
 int ovs_net_id __read_mostly;
 
+static struct genl_family dp_packet_genl_family;
+static struct genl_family dp_flow_genl_family;
+static struct genl_family dp_datapath_genl_family;
+
+static struct genl_multicast_group ovs_dp_flow_multicast_group = {
+   .name = OVS_FLOW_MCGROUP
+};
+
+static struct genl_multicast_group ovs_dp_datapath_multicast_group = {
+   .name = OVS_DATAPATH_MCGROUP
+};
+
+struct genl_multicast_group ovs_dp_vport_multicast_group = {
+   .name = OVS_VPORT_MCGROUP
+};
+
 /* Check if need to build a reply message.
  * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
 static bool ovs_must_notify(struct genl_info *info,
@@ -272,16 +288,6 @@ out:
u64_stats_update_end(stats-sync);
 }
 
-static struct genl_family dp_packet_genl_family = {
-   .id = GENL_ID_GENERATE,
-   .hdrsize = sizeof(struct ovs_header),
-   .name = OVS_PACKET_FAMILY,
-   .version = OVS_PACKET_VERSION,
-   .maxattr = OVS_PACKET_ATTR_MAX,
-   .netnsok = true,
-   .parallel_ops = true,
-};
-
 int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
  const struct dp_upcall_info *upcall_info)
 {
@@ -600,6 +606,18 @@ static const struct genl_ops dp_packet_genl_ops[] = {
}
 };
 
+static struct genl_family dp_packet_genl_family = {
+   .id = GENL_ID_GENERATE,
+   .hdrsize = sizeof(struct ovs_header),
+   .name = OVS_PACKET_FAMILY,
+   .version = OVS_PACKET_VERSION,
+   .maxattr = OVS_PACKET_ATTR_MAX,
+   .netnsok = true,
+   .parallel_ops = true,
+   .ops = dp_packet_genl_ops,
+   .n_ops = ARRAY_SIZE(dp_packet_genl_ops),
+};
+
 static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats,
 struct ovs_dp_megaflow_stats *mega_stats)
 {
@@ -631,26 +649,6 @@ static void get_dp_stats(struct datapath *dp, struct 
ovs_dp_stats *stats,
}
 }
 
-static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
-   [OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
-   [OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
-   [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
-};
-
-static struct genl_family dp_flow_genl_family = {
-   .id = GENL_ID_GENERATE,
-   .hdrsize = sizeof(struct ovs_header),
-   .name = OVS_FLOW_FAMILY,
-   .version = OVS_FLOW_VERSION,
-   .maxattr = OVS_FLOW_ATTR_MAX,
-   .netnsok = true,
-   .parallel_ops = true,
-};
-
-static struct genl_multicast_group ovs_dp_flow_multicast_group = {
-   .name = OVS_FLOW_MCGROUP
-};
-
 static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts)
 {
return NLMSG_ALIGN(sizeof(struct ovs_header))
@@ -1186,7 +1184,13 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct 
netlink_callback *cb)
return skb-len;
 }
 
-static const struct genl_ops dp_flow_genl_ops[] = {
+static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
+   [OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
+   [OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
+   [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
+};
+
+static struct genl_ops dp_flow_genl_ops[] = {
{ .cmd = OVS_FLOW_CMD_NEW,
  .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
  .policy = flow_policy,
@@ -1210,24 +1214,18 @@ static const struct genl_ops dp_flow_genl_ops[] = {
},
 };
 
-static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
-   [OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
-   [OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 },
-   [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
-};
-
-static struct genl_family dp_datapath_genl_family = {
+static struct genl_family dp_flow_genl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = sizeof(struct ovs_header),
-   .name = 

[linux-yocto] [PATCH 24/29] openvswitch: Minimize ovs_flow_cmd_new|set critical sections.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 893f139b9a6c00c097b9082a90f3041cfb3a0d20 upstream

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 192 +++--
 1 file changed, 116 insertions(+), 76 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index ce7fe6d..aedbd1d 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -796,8 +796,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
 {
struct nlattr **a = info-attrs;
struct ovs_header *ovs_header = info-userhdr;
-   struct sw_flow_key key, masked_key;
-   struct sw_flow *flow;
+   struct sw_flow *flow, *new_flow;
struct sw_flow_mask mask;
struct sk_buff *reply;
struct datapath *dp;
@@ -805,61 +804,77 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
struct sw_flow_match match;
int error;
 
-   /* Extract key. */
+   /* Must have key and actions. */
error = -EINVAL;
if (!a[OVS_FLOW_ATTR_KEY])
goto error;
+   if (!a[OVS_FLOW_ATTR_ACTIONS])
+   goto error;
 
-   ovs_match_init(match, key, mask);
+   /* Most of the time we need to allocate a new flow, do it before
+* locking.
+*/
+   new_flow = ovs_flow_alloc();
+   if (IS_ERR(new_flow)) {
+   error = PTR_ERR(new_flow);
+   goto error;
+   }
+
+   /* Extract key. */
+   ovs_match_init(match, new_flow-unmasked_key, mask);
error = ovs_nla_get_match(match,
  a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]);
if (error)
-   goto error;
+   goto err_kfree_flow;
 
-   /* Validate actions. */
-   error = -EINVAL;
-   if (!a[OVS_FLOW_ATTR_ACTIONS])
-   goto error;
+   ovs_flow_mask_key(new_flow-key, new_flow-unmasked_key, mask);
 
+   /* Validate actions. */
acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_FLOW_ATTR_ACTIONS]));
error = PTR_ERR(acts);
if (IS_ERR(acts))
-   goto error;
+   goto err_kfree_flow;
 
-   ovs_flow_mask_key(masked_key, key, mask);
-   error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS],
-masked_key, 0, acts);
+   error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], new_flow-key,
+0, acts);
if (error) {
OVS_NLERR(Flow actions may not be safe on all matching 
packets.\n);
-   goto err_kfree;
+   goto err_kfree_acts;
+   }
+
+   reply = ovs_flow_cmd_alloc_info(acts, info, false);
+   if (IS_ERR(reply)) {
+   error = PTR_ERR(reply);
+   goto err_kfree_acts;
}
 
ovs_lock();
dp = get_dp(sock_net(skb-sk), ovs_header-dp_ifindex);
-   error = -ENODEV;
-   if (!dp)
+   if (unlikely(!dp)) {
+   error = -ENODEV;
goto err_unlock_ovs;
-
+   }
/* Check if this is a duplicate flow */
-   flow = ovs_flow_tbl_lookup(dp-table, key);
-   if (!flow) {
-   /* Allocate flow. */
-   flow = ovs_flow_alloc();
-   if (IS_ERR(flow)) {
-   error = PTR_ERR(flow);
-   goto err_unlock_ovs;
-   }
-
-   flow-key = masked_key;
-   flow-unmasked_key = key;
-   rcu_assign_pointer(flow-sf_acts, acts);
+   flow = ovs_flow_tbl_lookup(dp-table, new_flow-unmasked_key);
+   if (likely(!flow)) {
+   rcu_assign_pointer(new_flow-sf_acts, acts);
 
/* Put flow in bucket. */
-   error = ovs_flow_tbl_insert(dp-table, flow, mask);
-   if (error) {
+   error = ovs_flow_tbl_insert(dp-table, new_flow, mask);
+   if (unlikely(error)) {
acts = NULL;
-   goto err_flow_free;
+   goto err_unlock_ovs;
}
+
+   if (unlikely(reply)) {
+   error = ovs_flow_cmd_fill_info(new_flow,
+  ovs_header-dp_ifindex,
+  reply, info-snd_portid,
+  info-snd_seq, 0,
+  OVS_FLOW_CMD_NEW);
+   BUG_ON(error  0);
+   }
+   ovs_unlock();
} else {
struct sw_flow_actions *old_acts;
 
@@ -869,39 +884,45 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
 * request.  We also accept 

[linux-yocto] [PATCH 20/29] openvswitch: Fix ovs_flow_stats_get/clear RCU dereference.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit 86ec8dbae27e5fa2b5d54f10f77286d9ef55732a upstream

For ovs_flow_stats_get() using ovsl_dereference() was wrong, since
flow dumps call this with RCU read lock.

ovs_flow_stats_clear() is always called with ovs_mutex, so can use
ovsl_dereference().

Also, make the ovs_flow_stats_get() 'flow' argument const to make
later patches cleaner.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/flow.c | 10 ++
 net/openvswitch/flow.h |  6 +++---
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 1019fc1..334751c 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -122,8 +122,9 @@ unlock:
spin_unlock(stats-lock);
 }
 
-/* Called with ovs_mutex. */
-void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats,
+/* Must be called with rcu_read_lock or ovs_mutex. */
+void ovs_flow_stats_get(const struct sw_flow *flow,
+   struct ovs_flow_stats *ovs_stats,
unsigned long *used, __be16 *tcp_flags)
 {
int node;
@@ -133,7 +134,7 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct 
ovs_flow_stats *ovs_stats,
memset(ovs_stats, 0, sizeof(*ovs_stats));
 
for_each_node(node) {
-   struct flow_stats *stats = ovsl_dereference(flow-stats[node]);
+   struct flow_stats *stats = 
rcu_dereference_ovsl(flow-stats[node]);
 
if (stats) {
/* Local CPU may write on non-local stats, so we must
@@ -150,12 +151,13 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct 
ovs_flow_stats *ovs_stats,
}
 }
 
+/* Called with ovs_mutex. */
 void ovs_flow_stats_clear(struct sw_flow *flow)
 {
int node;
 
for_each_node(node) {
-   struct flow_stats *stats = rcu_dereference(flow-stats[node]);
+   struct flow_stats *stats = ovsl_dereference(flow-stats[node]);
 
if (stats) {
spin_lock_bh(stats-lock);
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index a292bf8..ac395d2 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -180,10 +180,10 @@ struct arp_eth_header {
unsigned char   ar_tip[4];  /* target IP address*/
 } __packed;
 
-void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb);
-void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *stats,
+void ovs_flow_stats_update(struct sw_flow *, struct sk_buff *);
+void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
unsigned long *used, __be16 *tcp_flags);
-void ovs_flow_stats_clear(struct sw_flow *flow);
+void ovs_flow_stats_clear(struct sw_flow *);
 u64 ovs_flow_used_time(unsigned long flow_jiffies);
 
 int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *);
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 22/29] openvswitch: Minimize ovs_flow_cmd_del critical section.

2014-08-20 Thread zhe.he
From: Jarno Rajahalme jrajaha...@nicira.com

commit aed067783e505bf66dcafa8647d08619eb5b1c55 upstream

ovs_flow_cmd_del() now allocates reply (if needed) after the flow has
already been removed from the flow table.  If the reply allocation
fails, a netlink error is signaled with netlink_set_err(), as is
already done in ovs_flow_cmd_new_or_set() in the similar situation.

Signed-off-by: Jarno Rajahalme jrajaha...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c | 53 --
 1 file changed, 28 insertions(+), 25 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 91b4286..f9e6797 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -984,50 +984,53 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct 
genl_info *info)
struct sw_flow_match match;
int err;
 
+   if (likely(a[OVS_FLOW_ATTR_KEY])) {
+   ovs_match_init(match, key, NULL);
+   err = ovs_nla_get_match(match, a[OVS_FLOW_ATTR_KEY], NULL);
+   if (unlikely(err))
+   return err;
+   }
+
ovs_lock();
dp = get_dp(sock_net(skb-sk), ovs_header-dp_ifindex);
-   if (!dp) {
+   if (unlikely(!dp)) {
err = -ENODEV;
goto unlock;
}
 
-   if (!a[OVS_FLOW_ATTR_KEY]) {
+   if (unlikely(!a[OVS_FLOW_ATTR_KEY])) {
err = ovs_flow_tbl_flush(dp-table);
goto unlock;
}
 
-   ovs_match_init(match, key, NULL);
-   err = ovs_nla_get_match(match, a[OVS_FLOW_ATTR_KEY], NULL);
-   if (err)
-   goto unlock;
-
flow = ovs_flow_tbl_lookup(dp-table, key);
-   if (!flow || !ovs_flow_cmp_unmasked_key(flow, match)) {
+   if (unlikely(!flow || !ovs_flow_cmp_unmasked_key(flow, match))) {
err = -ENOENT;
goto unlock;
}
 
-   reply = ovs_flow_cmd_alloc_info(ovsl_dereference(flow-sf_acts), info,
-   false);
-   if (IS_ERR(reply)) {
-   err = PTR_ERR(reply);
-   goto unlock;
-   }
-
ovs_flow_tbl_remove(dp-table, flow);
+   ovs_unlock();
 
-   if (reply) {
-   err = ovs_flow_cmd_fill_info(flow, ovs_header-dp_ifindex,
-reply, info-snd_portid,
-info-snd_seq, 0,
-OVS_FLOW_CMD_DEL);
-   BUG_ON(err  0);
+   reply = ovs_flow_cmd_alloc_info((const struct sw_flow_actions __force 
*) flow-sf_acts,
+   info, false);
+   if (likely(reply)) {
+   if (likely(!IS_ERR(reply))) {
+   rcu_read_lock();/*To keep RCU checker happy. */
+   err = ovs_flow_cmd_fill_info(flow, 
ovs_header-dp_ifindex,
+reply, info-snd_portid,
+info-snd_seq, 0,
+OVS_FLOW_CMD_DEL);
+   rcu_read_unlock();
+   BUG_ON(err  0);
+
+   ovs_notify(dp_flow_genl_family, reply, info);
+   } else {
+   netlink_set_err(sock_net(skb-sk)-genl_sock, 0, 0, 
PTR_ERR(reply));
+   }
}
-   ovs_flow_free(flow, true);
-   ovs_unlock();
 
-   if (reply)
-   ovs_notify(dp_flow_genl_family, reply, info);
+   ovs_flow_free(flow, true);
return 0;
 unlock:
ovs_unlock();
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 27/29] openvswitch: supply a dummy err_handler of gre_cisco_protocol to prevent kernel crash

2014-08-20 Thread zhe.he
From: Wei Zhang asuka@163.com

commit e0bb8c44ed5cfcc56b571758ed966ee48779024c upstream

When use gre vport, openvswitch register a gre_cisco_protocol but
does not supply a err_handler with it. The gre_cisco_err() in
net/ipv4/gre_demux.c expect err_handler be provided with the
gre_cisco_protocol implementation, and call -err_handler() without
existence check, cause the kernel crash.

This patch provide a err_handler to fix this bug.
This bug introduced by commit aa310701e787087d (openvswitch: Add gre
tunnel support.)

Signed-off-by: Wei Zhang asuka@163.com
Signed-off-by: Jesse Gross je...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/vport-gre.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index a0da2dd..5c3da02 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -110,6 +110,22 @@ static int gre_rcv(struct sk_buff *skb,
return PACKET_RCVD;
 }
 
+/* Called with rcu_read_lock and BH disabled. */
+static int gre_err(struct sk_buff *skb, u32 info,
+  const struct tnl_ptk_info *tpi)
+{
+   struct ovs_net *ovs_net;
+   struct vport *vport;
+
+   ovs_net = net_generic(dev_net(skb-dev), ovs_net_id);
+   vport = rcu_dereference(ovs_net-vport_net.gre_vport);
+
+   if (unlikely(!vport))
+   return PACKET_REJECT;
+   else
+   return PACKET_RCVD;
+}
+
 static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
 {
struct net *net = ovs_dp_get_net(vport-dp);
@@ -186,6 +202,7 @@ error:
 
 static struct gre_cisco_protocol gre_protocol = {
.handler= gre_rcv,
+   .err_handler= gre_err,
.priority   = 1,
 };
 
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 29/29] openvswitch: Use exact lookup for flow_get and flow_del.

2014-08-20 Thread zhe.he
From: Alex Wang al...@nicira.com

commit 4a46b24e147dfa9b858026da02cad0bdd4e149d2 upstream

Due to the race condition in userspace, there is chance that two
overlapping megaflows could be installed in datapath.  And this
causes userspace unable to delete the less inclusive megaflow flow
even after it timeout, since the flow_del logic will stop at the
first match of masked flow.

This commit fixes the bug by making the kernel flow_del and flow_get
logic check all masks in that case.

Introduced by 03f0d916a (openvswitch: Mega flow implementation).

Signed-off-by: Alex Wang al...@nicira.com
Acked-by: Andy Zhou az...@nicira.com
Signed-off-by: Pravin B Shelar pshe...@nicira.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 net/openvswitch/datapath.c   | 23 +++
 net/openvswitch/flow_table.c | 16 
 net/openvswitch/flow_table.h |  3 ++-
 3 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 4c5d49d..b51cc9f 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -889,8 +889,11 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct 
genl_info *info)
}
/* The unmasked key has to be the same for flow updates. */
if (unlikely(!ovs_flow_cmp_unmasked_key(flow, match))) {
-   error = -EEXIST;
-   goto err_unlock_ovs;
+   flow = ovs_flow_tbl_lookup_exact(dp-table, match);
+   if (!flow) {
+   error = -ENOENT;
+   goto err_unlock_ovs;
+   }
}
/* Update actions. */
old_acts = ovsl_dereference(flow-sf_acts);
@@ -981,16 +984,12 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct 
genl_info *info)
goto err_unlock_ovs;
}
/* Check that the flow exists. */
-   flow = ovs_flow_tbl_lookup(dp-table, key);
+   flow = ovs_flow_tbl_lookup_exact(dp-table, match);
if (unlikely(!flow)) {
error = -ENOENT;
goto err_unlock_ovs;
}
-   /* The unmasked key has to be the same for flow updates. */
-   if (unlikely(!ovs_flow_cmp_unmasked_key(flow, match))) {
-   error = -EEXIST;
-   goto err_unlock_ovs;
-   }
+
/* Update actions, if present. */
if (likely(acts)) {
old_acts = ovsl_dereference(flow-sf_acts);
@@ -1063,8 +1062,8 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct 
genl_info *info)
goto unlock;
}
 
-   flow = ovs_flow_tbl_lookup(dp-table, key);
-   if (!flow || !ovs_flow_cmp_unmasked_key(flow, match)) {
+   flow = ovs_flow_tbl_lookup_exact(dp-table, match);
+   if (!flow) {
err = -ENOENT;
goto unlock;
}
@@ -1113,8 +1112,8 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct 
genl_info *info)
goto unlock;
}
 
-   flow = ovs_flow_tbl_lookup(dp-table, key);
-   if (unlikely(!flow || !ovs_flow_cmp_unmasked_key(flow, match))) {
+   flow = ovs_flow_tbl_lookup_exact(dp-table, match);
+   if (unlikely(!flow)) {
err = -ENOENT;
goto unlock;
}
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index 574c3ab..cf2d853 100644
--- a/net/openvswitch/flow_table.c
+++ b/net/openvswitch/flow_table.c
@@ -456,6 +456,22 @@ struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl,
return ovs_flow_tbl_lookup_stats(tbl, key, n_mask_hit);
 }
 
+struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
+ struct sw_flow_match *match)
+{
+   struct table_instance *ti = rcu_dereference_ovsl(tbl-ti);
+   struct sw_flow_mask *mask;
+   struct sw_flow *flow;
+
+   /* Always called under ovs-mutex. */
+   list_for_each_entry(mask, tbl-mask_list, list) {
+   flow = masked_flow_lookup(ti, match-key, mask);
+   if (flow  ovs_flow_cmp_unmasked_key(flow, match))  /* Found */
+   return flow;
+   }
+   return NULL;
+}
+
 int ovs_flow_tbl_num_masks(const struct flow_table *table)
 {
struct sw_flow_mask *mask;
diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h
index ca8a582..5918bff 100644
--- a/net/openvswitch/flow_table.h
+++ b/net/openvswitch/flow_table.h
@@ -76,7 +76,8 @@ struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *,
u32 *n_mask_hit);
 struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
const struct sw_flow_key *);
-
+struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
+ struct sw_flow_match *match);
 bool ovs_flow_cmp_unmasked_key(const 

[linux-yocto] [PATCH 01/10] vhost: don't open-code sockfd_put()

2014-08-20 Thread zhe.he
From: Al Viro v...@zeniv.linux.org.uk

commit 09aaacf02a3e88870ed5cad038a5bc822c947904 upstream

Signed-off-by: Al Viro v...@zeniv.linux.org.uk
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/net.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index e1e22e0..be414d2 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -818,9 +818,9 @@ static int vhost_net_release(struct inode *inode, struct 
file *f)
vhost_dev_cleanup(n-dev, false);
vhost_net_vq_reset(n);
if (tx_sock)
-   fput(tx_sock-file);
+   sockfd_put(tx_sock);
if (rx_sock)
-   fput(rx_sock-file);
+   sockfd_put(rx_sock);
/* Make sure no callbacks are outstanding */
synchronize_rcu_bh();
/* We do an extra flush before freeing memory,
@@ -860,7 +860,7 @@ static struct socket *get_raw_socket(int fd)
}
return sock;
 err:
-   fput(sock-file);
+   sockfd_put(sock);
return ERR_PTR(r);
 }
 
@@ -966,7 +966,7 @@ static long vhost_net_set_backend(struct vhost_net *n, 
unsigned index, int fd)
 
if (oldsock) {
vhost_net_flush_vq(n, index);
-   fput(oldsock-file);
+   sockfd_put(oldsock);
}
 
mutex_unlock(n-dev.mutex);
@@ -978,7 +978,7 @@ err_used:
if (ubufs)
vhost_net_ubuf_put_wait_and_free(ubufs);
 err_ubufs:
-   fput(sock-file);
+   sockfd_put(sock);
 err_vq:
mutex_unlock(vq-mutex);
 err:
@@ -1009,9 +1009,9 @@ static long vhost_net_reset_owner(struct vhost_net *n)
 done:
mutex_unlock(n-dev.mutex);
if (tx_sock)
-   fput(tx_sock-file);
+   sockfd_put(tx_sock);
if (rx_sock)
-   fput(rx_sock-file);
+   sockfd_put(rx_sock);
return err;
 }
 
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 03/10] vhost/scsi: Add preallocation of protection SGLs

2014-08-20 Thread zhe.he
From: Nicholas Bellinger n...@linux-iscsi.org

commit b1935f687bb93b207ef690f7debc0e9921fc484f upstream

This patch updates tcm_vhost_make_nexus() to pre-allocate per descriptor
tcm_vhost_cmd-tvc_prot_sgl[] used to expose protection SGLs from within
virtio-scsi guest memory to vhost-scsi.

Cc: Michael S. Tsirkin m...@redhat.com
Cc: Paolo Bonzini pbonz...@redhat.com
Cc: Martin K. Petersen martin.peter...@oracle.com
Cc: Christoph Hellwig h...@lst.de
Cc: Hannes Reinecke h...@suse.de
Acked-by: Michael S. Tsirkin m...@redhat.com
Signed-off-by: Nicholas Bellinger n...@linux-iscsi.org
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/scsi.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 45e64cc..038fc5e 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -58,6 +58,7 @@
 #define TCM_VHOST_DEFAULT_TAGS 256
 #define TCM_VHOST_PREALLOC_SGLS 2048
 #define TCM_VHOST_PREALLOC_UPAGES 2048
+#define TCM_VHOST_PREALLOC_PROT_SGLS 512
 
 struct vhost_scsi_inflight {
/* Wait for the flush operation to finish */
@@ -83,6 +84,7 @@ struct tcm_vhost_cmd {
u32 tvc_lun;
/* Pointer to the SGL formatted memory from virtio-scsi */
struct scatterlist *tvc_sgl;
+   struct scatterlist *tvc_prot_sgl;
struct page **tvc_upages;
/* Pointer to response */
struct virtio_scsi_cmd_resp __user *tvc_resp;
@@ -717,7 +719,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
struct tcm_vhost_cmd *cmd;
struct tcm_vhost_nexus *tv_nexus;
struct se_session *se_sess;
-   struct scatterlist *sg;
+   struct scatterlist *sg, *prot_sg;
struct page **pages;
int tag;
 
@@ -736,10 +738,12 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
 
cmd = ((struct tcm_vhost_cmd *)se_sess-sess_cmd_map)[tag];
sg = cmd-tvc_sgl;
+   prot_sg = cmd-tvc_prot_sgl;
pages = cmd-tvc_upages;
memset(cmd, 0, sizeof(struct tcm_vhost_cmd));
 
cmd-tvc_sgl = sg;
+   cmd-tvc_prot_sgl = prot_sg;
cmd-tvc_upages = pages;
cmd-tvc_se_cmd.map_tag = tag;
cmd-tvc_tag = v_req-tag;
@@ -1698,6 +1702,7 @@ static void tcm_vhost_free_cmd_map_res(struct 
tcm_vhost_nexus *nexus,
tv_cmd = ((struct tcm_vhost_cmd *)se_sess-sess_cmd_map)[i];
 
kfree(tv_cmd-tvc_sgl);
+   kfree(tv_cmd-tvc_prot_sgl);
kfree(tv_cmd-tvc_upages);
}
 }
@@ -1756,6 +1761,14 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg 
*tpg,
pr_err(Unable to allocate tv_cmd-tvc_upages\n);
goto out;
}
+
+   tv_cmd-tvc_prot_sgl = kzalloc(sizeof(struct scatterlist) *
+   TCM_VHOST_PREALLOC_PROT_SGLS, 
GFP_KERNEL);
+   if (!tv_cmd-tvc_prot_sgl) {
+   mutex_unlock(tpg-tv_tpg_mutex);
+   pr_err(Unable to allocate tv_cmd-tvc_prot_sgl\n);
+   goto out;
+   }
}
/*
 * Since we are running in 'demo mode' this call with generate a
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 02/10] vhost/scsi: Move sanity check into vhost_scsi_map_iov_to_sgl

2014-08-20 Thread zhe.he
From: Nicholas Bellinger n...@linux-iscsi.org

commit 5a01d08217e39f3d36d3ca160361c7b019ff1598 upstream

Move the overflow check for sgl_count  TCM_VHOST_PREALLOC_SGLS into
vhost_scsi_map_iov_to_sgl() so that it's based on the total number
of SGLs for all IOVs, instead of single IOVs.

Also, rename TCM_VHOST_PREALLOC_PAGES - TCM_VHOST_PREALLOC_UPAGES
to better describe pointers to user-space pages.

Cc: Michael S. Tsirkin m...@redhat.com
Cc: Paolo Bonzini pbonz...@redhat.com
Cc: Martin K. Petersen martin.peter...@oracle.com
Cc: Christoph Hellwig h...@lst.de
Cc: Hannes Reinecke h...@suse.de
Acked-by: Michael S. Tsirkin m...@redhat.com
Signed-off-by: Nicholas Bellinger n...@linux-iscsi.org
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/scsi.c | 59 ++--
 1 file changed, 25 insertions(+), 34 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index e48d4a6..45e64cc 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -57,7 +57,7 @@
 #define TCM_VHOST_MAX_CDB_SIZE 32
 #define TCM_VHOST_DEFAULT_TAGS 256
 #define TCM_VHOST_PREALLOC_SGLS 2048
-#define TCM_VHOST_PREALLOC_PAGES 2048
+#define TCM_VHOST_PREALLOC_UPAGES 2048
 
 struct vhost_scsi_inflight {
/* Wait for the flush operation to finish */
@@ -762,35 +762,28 @@ vhost_scsi_map_to_sgl(struct tcm_vhost_cmd *tv_cmd,
  struct scatterlist *sgl,
  unsigned int sgl_count,
  struct iovec *iov,
- int write)
+ struct page **pages,
+ bool write)
 {
unsigned int npages = 0, pages_nr, offset, nbytes;
struct scatterlist *sg = sgl;
void __user *ptr = iov-iov_base;
size_t len = iov-iov_len;
-   struct page **pages;
int ret, i;
 
-   if (sgl_count  TCM_VHOST_PREALLOC_SGLS) {
-   pr_err(vhost_scsi_map_to_sgl() psgl_count: %u greater than
-   preallocated TCM_VHOST_PREALLOC_SGLS: %u\n,
-   sgl_count, TCM_VHOST_PREALLOC_SGLS);
-   return -ENOBUFS;
-   }
-
pages_nr = iov_num_pages(iov);
-   if (pages_nr  sgl_count)
+   if (pages_nr  sgl_count) {
+   pr_err(vhost_scsi_map_to_sgl() pages_nr: %u greater than
+   sgl_count: %u\n, pages_nr, sgl_count);
return -ENOBUFS;
-
-   if (pages_nr  TCM_VHOST_PREALLOC_PAGES) {
+   }
+   if (pages_nr  TCM_VHOST_PREALLOC_UPAGES) {
pr_err(vhost_scsi_map_to_sgl() pages_nr: %u greater than
-   preallocated TCM_VHOST_PREALLOC_PAGES: %u\n,
-   pages_nr, TCM_VHOST_PREALLOC_PAGES);
+   preallocated TCM_VHOST_PREALLOC_UPAGES: %u\n,
+   pages_nr, TCM_VHOST_PREALLOC_UPAGES);
return -ENOBUFS;
}
 
-   pages = tv_cmd-tvc_upages;
-
ret = get_user_pages_fast((unsigned long)ptr, pages_nr, write, pages);
/* No pages were pinned */
if (ret  0)
@@ -820,33 +813,32 @@ out:
 static int
 vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
  struct iovec *iov,
- unsigned int niov,
- int write)
+ int niov,
+ bool write)
 {
-   int ret;
-   unsigned int i;
-   u32 sgl_count;
-   struct scatterlist *sg;
+   struct scatterlist *sg = cmd-tvc_sgl;
+   unsigned int sgl_count = 0;
+   int ret, i;
 
-   /*
-* Find out how long sglist needs to be
-*/
-   sgl_count = 0;
for (i = 0; i  niov; i++)
sgl_count += iov_num_pages(iov[i]);
 
-   /* TODO overflow checking */
+   if (sgl_count  TCM_VHOST_PREALLOC_SGLS) {
+   pr_err(vhost_scsi_map_iov_to_sgl() sgl_count: %u greater than
+preallocated TCM_VHOST_PREALLOC_SGLS: %u\n,
+   sgl_count, TCM_VHOST_PREALLOC_SGLS);
+   return -ENOBUFS;
+   }
 
-   sg = cmd-tvc_sgl;
pr_debug(%s sg %p sgl_count %u\n, __func__, sg, sgl_count);
sg_init_table(sg, sgl_count);
-
cmd-tvc_sgl_count = sgl_count;
 
-   pr_debug(Mapping %u iovecs for %u pages\n, niov, sgl_count);
+   pr_debug(Mapping iovec %p for %u pages\n, iov[0], sgl_count);
+
for (i = 0; i  niov; i++) {
ret = vhost_scsi_map_to_sgl(cmd, sg, sgl_count, iov[i],
-   write);
+   cmd-tvc_upages, write);
if (ret  0) {
for (i = 0; i  cmd-tvc_sgl_count; i++)
put_page(sg_page(cmd-tvc_sgl[i]));
@@ -854,7 +846,6 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
cmd-tvc_sgl_count = 0;
return ret;
}
-
 

[linux-yocto] [PATCH 08/10] vhost: move acked_features to VQs

2014-08-20 Thread zhe.he
From: Michael S. Tsirkin m...@redhat.com

commit ea16c51433510f7f758382dec5b933fc0797f244 upstream

Refactor code to make sure features are only accessed
under VQ mutex. This makes everything simpler, no need
for RCU here anymore.

Signed-off-by: Michael S. Tsirkin m...@redhat.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/net.c   |  8 +++-
 drivers/vhost/scsi.c  | 22 +-
 drivers/vhost/test.c  |  9 ++---
 drivers/vhost/vhost.c | 36 +++-
 drivers/vhost/vhost.h | 11 +++
 5 files changed, 44 insertions(+), 42 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index e489161..2bc8f29 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -585,9 +585,9 @@ static void handle_rx(struct vhost_net *net)
vhost_hlen = nvq-vhost_hlen;
sock_hlen = nvq-sock_hlen;
 
-   vq_log = unlikely(vhost_has_feature(net-dev, VHOST_F_LOG_ALL)) ?
+   vq_log = unlikely(vhost_has_feature(vq, VHOST_F_LOG_ALL)) ?
vq-log : NULL;
-   mergeable = vhost_has_feature(net-dev, VIRTIO_NET_F_MRG_RXBUF);
+   mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF);
 
while ((sock_len = peek_head_len(sock-sk))) {
sock_len += sock_hlen;
@@ -1051,15 +1051,13 @@ static int vhost_net_set_features(struct vhost_net *n, 
u64 features)
mutex_unlock(n-dev.mutex);
return -EFAULT;
}
-   n-dev.acked_features = features;
-   smp_wmb();
for (i = 0; i  VHOST_NET_VQ_MAX; ++i) {
mutex_lock(n-vqs[i].vq.mutex);
+   n-vqs[i].vq.acked_features = features;
n-vqs[i].vhost_hlen = vhost_hlen;
n-vqs[i].sock_hlen = sock_hlen;
mutex_unlock(n-vqs[i].vq.mutex);
}
-   vhost_net_flush(n);
mutex_unlock(n-dev.mutex);
return 0;
 }
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 752988a..cc2f264 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1474,6 +1474,9 @@ err_dev:
 
 static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
 {
+   struct vhost_virtqueue *vq;
+   int i;
+
if (features  ~VHOST_SCSI_FEATURES)
return -EOPNOTSUPP;
 
@@ -1483,9 +1486,13 @@ static int vhost_scsi_set_features(struct vhost_scsi 
*vs, u64 features)
mutex_unlock(vs-dev.mutex);
return -EFAULT;
}
-   vs-dev.acked_features = features;
-   smp_wmb();
-   vhost_scsi_flush(vs);
+
+   for (i = 0; i  VHOST_SCSI_MAX_VQ; i++) {
+   vq = vs-vqs[i].vq;
+   mutex_lock(vq-mutex);
+   vq-acked_features = features;
+   mutex_unlock(vq-mutex);
+   }
mutex_unlock(vs-dev.mutex);
return 0;
 }
@@ -1692,10 +1699,6 @@ tcm_vhost_do_plug(struct tcm_vhost_tpg *tpg,
return;
 
mutex_lock(vs-dev.mutex);
-   if (!vhost_has_feature(vs-dev, VIRTIO_SCSI_F_HOTPLUG)) {
-   mutex_unlock(vs-dev.mutex);
-   return;
-   }
 
if (plug)
reason = VIRTIO_SCSI_EVT_RESET_RESCAN;
@@ -1704,8 +1707,9 @@ tcm_vhost_do_plug(struct tcm_vhost_tpg *tpg,
 
vq = vs-vqs[VHOST_SCSI_VQ_EVT].vq;
mutex_lock(vq-mutex);
-   tcm_vhost_send_evt(vs, tpg, lun,
-   VIRTIO_SCSI_T_TRANSPORT_RESET, reason);
+   if (vhost_has_feature(vq, VIRTIO_SCSI_F_HOTPLUG))
+   tcm_vhost_send_evt(vs, tpg, lun,
+  VIRTIO_SCSI_T_TRANSPORT_RESET, reason);
mutex_unlock(vq-mutex);
mutex_unlock(vs-dev.mutex);
 }
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index c2a54fb..6fa3bf8 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -241,15 +241,18 @@ done:
 
 static int vhost_test_set_features(struct vhost_test *n, u64 features)
 {
+   struct vhost_virtqueue *vq;
+
mutex_lock(n-dev.mutex);
if ((features  (1  VHOST_F_LOG_ALL)) 
!vhost_log_access_ok(n-dev)) {
mutex_unlock(n-dev.mutex);
return -EFAULT;
}
-   n-dev.acked_features = features;
-   smp_wmb();
-   vhost_test_flush(n);
+   vq = n-vqs[VHOST_TEST_VQ];
+   mutex_lock(vq-mutex);
+   vq-acked_features = features;
+   mutex_unlock(vq-mutex);
mutex_unlock(n-dev.mutex);
return 0;
 }
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 1c05e60..a23870c 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -191,6 +191,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq-log_used = false;
vq-log_addr = -1ull;
vq-private_data = NULL;
+   vq-acked_features = 0;
vq-log_base = NULL;
vq-error_ctx = NULL;
vq-error = NULL;
@@ -524,11 +525,13 @@ static int memory_access_ok(struct vhost_dev *d, struct 
vhost_memory *mem,
 

[linux-yocto] [PATCH 05/10] vhost/scsi: Enable T10 PI IOV - SGL memory mapping

2014-08-20 Thread zhe.he
From: Nicholas Bellinger n...@linux-iscsi.org

commit 95e7c4341b8e28dae5204378087c1e2a115abc82 upstream

This patch updates vhost_scsi_handle_vq() to check for the existance
of virtio_scsi_cmd_req_pi comparing vq-iov[0].iov_len in order to
calculate seperate data + protection SGLs from data_num.

Also update tcm_vhost_submission_work() to pass the pre-allocated
cmd-tvc_prot_sgl[] memory into target_submit_cmd_map_sgls(), and
update vhost_scsi_get_tag() parameters to accept scsi_tag, lun, and
task_attr.

Cc: Michael S. Tsirkin m...@redhat.com
Cc: Paolo Bonzini pbonz...@redhat.com
Cc: Martin K. Petersen martin.peter...@oracle.com
Cc: Christoph Hellwig h...@lst.de
Cc: Hannes Reinecke h...@suse.de
Cc: Sagi Grimberg sa...@dev.mellanox.co.il
Cc: H. Peter Anvin h...@zytor.com
Acked-by: Michael S. Tsirkin m...@redhat.com
Signed-off-by: Nicholas Bellinger n...@linux-iscsi.org

[ Note: Remove the hunk for the parameter of transport_init_session_tags since
  the parameter is not included in this set of patches.- He Zhe ]
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/scsi.c | 181 ++-
 1 file changed, 123 insertions(+), 58 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 31d3b93..752988a 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -169,7 +169,8 @@ enum {
 };
 
 enum {
-   VHOST_SCSI_FEATURES = VHOST_FEATURES | (1ULL  VIRTIO_SCSI_F_HOTPLUG)
+   VHOST_SCSI_FEATURES = VHOST_FEATURES | (1ULL  VIRTIO_SCSI_F_HOTPLUG) |
+  (1ULL  VIRTIO_SCSI_F_T10_PI)
 };
 
 #define VHOST_SCSI_MAX_TARGET  256
@@ -715,11 +716,9 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work 
*work)
 }
 
 static struct tcm_vhost_cmd *
-vhost_scsi_get_tag(struct vhost_virtqueue *vq,
-   struct tcm_vhost_tpg *tpg,
-   struct virtio_scsi_cmd_req *v_req,
-   u32 exp_data_len,
-   int data_direction)
+vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct tcm_vhost_tpg *tpg,
+  unsigned char *cdb, u64 scsi_tag, u16 lun, u8 task_attr,
+  u32 exp_data_len, int data_direction)
 {
struct tcm_vhost_cmd *cmd;
struct tcm_vhost_nexus *tv_nexus;
@@ -751,13 +750,16 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
cmd-tvc_prot_sgl = prot_sg;
cmd-tvc_upages = pages;
cmd-tvc_se_cmd.map_tag = tag;
-   cmd-tvc_tag = v_req-tag;
-   cmd-tvc_task_attr = v_req-task_attr;
+   cmd-tvc_tag = scsi_tag;
+   cmd-tvc_lun = lun;
+   cmd-tvc_task_attr = task_attr;
cmd-tvc_exp_data_len = exp_data_len;
cmd-tvc_data_direction = data_direction;
cmd-tvc_nexus = tv_nexus;
cmd-inflight = tcm_vhost_get_inflight(vq);
 
+   memcpy(cmd-tvc_cdb, cdb, TCM_VHOST_MAX_CDB_SIZE);
+
return cmd;
 }
 
@@ -908,18 +910,17 @@ static void tcm_vhost_submission_work(struct work_struct 
*work)
container_of(work, struct tcm_vhost_cmd, work);
struct tcm_vhost_nexus *tv_nexus;
struct se_cmd *se_cmd = cmd-tvc_se_cmd;
-   struct scatterlist *sg_ptr, *sg_bidi_ptr = NULL;
-   int rc, sg_no_bidi = 0;
+   struct scatterlist *sg_ptr, *sg_prot_ptr = NULL;
+   int rc;
 
+   /* FIXME: BIDI operation */
if (cmd-tvc_sgl_count) {
sg_ptr = cmd-tvc_sgl;
-/* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */
-#if 0
-   if (se_cmd-se_cmd_flags  SCF_BIDI) {
-   sg_bidi_ptr = NULL;
-   sg_no_bidi = 0;
-   }
-#endif
+
+   if (cmd-tvc_prot_sgl_count)
+   sg_prot_ptr = cmd-tvc_prot_sgl;
+   else
+   se_cmd-prot_pto = true;
} else {
sg_ptr = NULL;
}
@@ -930,7 +931,7 @@ static void tcm_vhost_submission_work(struct work_struct 
*work)
cmd-tvc_lun, cmd-tvc_exp_data_len,
cmd-tvc_task_attr, cmd-tvc_data_direction,
TARGET_SCF_ACK_KREF, sg_ptr, cmd-tvc_sgl_count,
-   sg_bidi_ptr, sg_no_bidi, NULL, 0);
+   NULL, 0, sg_prot_ptr, cmd-tvc_prot_sgl_count);
if (rc  0) {
transport_send_check_condition_and_sense(se_cmd,
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
@@ -962,12 +963,18 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct 
vhost_virtqueue *vq)
 {
struct tcm_vhost_tpg **vs_tpg;
struct virtio_scsi_cmd_req v_req;
+   struct virtio_scsi_cmd_req_pi v_req_pi;
struct tcm_vhost_tpg *tpg;
struct tcm_vhost_cmd *cmd;
-   u32 exp_data_len, data_first, data_num, data_direction;
+   u64 tag;
+   u32 exp_data_len, data_first, data_num, data_direction, prot_first;
unsigned out, in, i;
-   int head, ret;

[linux-yocto] [PATCH 09/10] vhost: move memory pointer to VQs

2014-08-20 Thread zhe.he
From: Michael S. Tsirkin m...@redhat.com

commit 47283bef7ed356629467d1fac61687756e48f254 upstream

commit 2ae76693b8bcabf370b981cd00c36cd41d33fabc
vhost: replace rcu with mutex
replaced rcu sync for memory accesses with VQ mutex locl/unlock.
This is correct since all accesses are under VQ mutex, but incomplete:
we still do useless rcu lock/unlock operations, someone might copy this
code into some other context where this won't be right.
This use of RCU is also non standard and hard to understand.
Let's copy the pointer to each VQ structure, this way
the access rules become straight-forward, and there's
no need for RCU anymore.

Reported-by: Eric Dumazet eric.duma...@gmail.com
Signed-off-by: Michael S. Tsirkin m...@redhat.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/net.c   |  4 ++--
 drivers/vhost/scsi.c  |  4 ++--
 drivers/vhost/test.c  |  2 +-
 drivers/vhost/vhost.c | 57 ++-
 drivers/vhost/vhost.h |  8 +++-
 5 files changed, 33 insertions(+), 42 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 2bc8f29..971a760 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -374,7 +374,7 @@ static void handle_tx(struct vhost_net *net)
  % UIO_MAXIOV == nvq-done_idx))
break;
 
-   head = vhost_get_vq_desc(net-dev, vq, vq-iov,
+   head = vhost_get_vq_desc(vq, vq-iov,
 ARRAY_SIZE(vq-iov),
 out, in,
 NULL, NULL);
@@ -506,7 +506,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
r = -ENOBUFS;
goto err;
}
-   r = vhost_get_vq_desc(vq-dev, vq, vq-iov + seg,
+   r = vhost_get_vq_desc(vq, vq-iov + seg,
  ARRAY_SIZE(vq-iov) - seg, out,
  in, log, log_num);
if (unlikely(r  0))
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index cc2f264..3671d65 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -609,7 +609,7 @@ tcm_vhost_do_evt_work(struct vhost_scsi *vs, struct 
tcm_vhost_evt *evt)
 
 again:
vhost_disable_notify(vs-dev, vq);
-   head = vhost_get_vq_desc(vs-dev, vq, vq-iov,
+   head = vhost_get_vq_desc(vq, vq-iov,
ARRAY_SIZE(vq-iov), out, in,
NULL, NULL);
if (head  0) {
@@ -988,7 +988,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct 
vhost_virtqueue *vq)
vhost_disable_notify(vs-dev, vq);
 
for (;;) {
-   head = vhost_get_vq_desc(vs-dev, vq, vq-iov,
+   head = vhost_get_vq_desc(vq, vq-iov,
ARRAY_SIZE(vq-iov), out, in,
NULL, NULL);
pr_debug(vhost_get_vq_desc: head: %d, out: %u in: %u\n,
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index 6fa3bf8..d9c501e 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -53,7 +53,7 @@ static void handle_vq(struct vhost_test *n)
vhost_disable_notify(n-dev, vq);
 
for (;;) {
-   head = vhost_get_vq_desc(n-dev, vq, vq-iov,
+   head = vhost_get_vq_desc(vq, vq-iov,
 ARRAY_SIZE(vq-iov),
 out, in,
 NULL, NULL);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index a23870c..c90f437 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -18,7 +18,6 @@
 #include linux/mmu_context.h
 #include linux/miscdevice.h
 #include linux/mutex.h
-#include linux/rcupdate.h
 #include linux/poll.h
 #include linux/file.h
 #include linux/highmem.h
@@ -199,6 +198,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq-call_ctx = NULL;
vq-call = NULL;
vq-log_ctx = NULL;
+   vq-memory = NULL;
 }
 
 static int vhost_worker(void *data)
@@ -416,11 +416,18 @@ EXPORT_SYMBOL_GPL(vhost_dev_reset_owner_prepare);
 /* Caller should have device mutex */
 void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_memory *memory)
 {
+   int i;
+
vhost_dev_cleanup(dev, true);
 
/* Restore memory to default empty mapping. */
memory-nregions = 0;
-   RCU_INIT_POINTER(dev-memory, memory);
+   dev-memory = memory;
+   /* We don't need VQ locks below since vhost_dev_cleanup makes sure
+* VQs aren't running.
+*/
+   for (i = 0; i  dev-nvqs; ++i)
+   dev-vqs[i]-memory = memory;
 }
 EXPORT_SYMBOL_GPL(vhost_dev_reset_owner);
 
@@ -463,10 +470,8 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked)
fput(dev-log_file);
dev-log_file = NULL;
/* No one will access memory at this point */
-  

[linux-yocto] [PATCH 06/10] vhost-net: extend device allocation to vmalloc

2014-08-20 Thread zhe.he
From: Michael S. Tsirkin m...@redhat.com

commit 23cc5a991c7a9fb7e6d6550e65cee4f4173111c5 upstream

Michael Mueller provided a patch to reduce the size of
vhost-net structure as some allocations could fail under
memory pressure/fragmentation. We are still left with
high order allocations though.

This patch is handling the problem at the core level, allowing
vhost structures to use vmalloc() if kmalloc() failed.

As vmalloc() adds overhead on a critical network path, add __GFP_REPEAT
to kzalloc() flags to do this fallback only when really needed.

People are still looking at cleaner ways to handle the problem
at the API level, probably passing in multiple iovecs.
This hack seems consistent with approaches
taken since then by drivers/vhost/scsi.c and net/core/dev.c

Based on patch by Romain Francoise.

Cc: Michael Mueller m...@linux.vnet.ibm.com
Signed-off-by: Romain Francoise rom...@orebokech.com
Acked-by: Michael S. Tsirkin m...@redhat.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/net.c | 23 ++-
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index be414d2..e489161 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -17,6 +17,7 @@
 #include linux/workqueue.h
 #include linux/file.h
 #include linux/slab.h
+#include linux/vmalloc.h
 
 #include linux/net.h
 #include linux/if_packet.h
@@ -699,18 +700,30 @@ static void handle_rx_net(struct vhost_work *work)
handle_rx(net);
 }
 
+static void vhost_net_free(void *addr)
+{
+   if (is_vmalloc_addr(addr))
+   vfree(addr);
+   else
+   kfree(addr);
+}
+
 static int vhost_net_open(struct inode *inode, struct file *f)
 {
-   struct vhost_net *n = kmalloc(sizeof *n, GFP_KERNEL);
+   struct vhost_net *n;
struct vhost_dev *dev;
struct vhost_virtqueue **vqs;
int i;
 
-   if (!n)
-   return -ENOMEM;
+   n = kmalloc(sizeof *n, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+   if (!n) {
+   n = vmalloc(sizeof *n);
+   if (!n)
+   return -ENOMEM;
+   }
vqs = kmalloc(VHOST_NET_VQ_MAX * sizeof(*vqs), GFP_KERNEL);
if (!vqs) {
-   kfree(n);
+   vhost_net_free(n);
return -ENOMEM;
}
 
@@ -827,7 +840,7 @@ static int vhost_net_release(struct inode *inode, struct 
file *f)
 * since jobs can re-queue themselves. */
vhost_net_flush(n);
kfree(n-dev.vqs);
-   kfree(n);
+   vhost_net_free(n);
return 0;
 }
 
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 07/10] vhost: replace rcu with mutex

2014-08-20 Thread zhe.he
From: Michael S. Tsirkin m...@redhat.com

commit 98f9ca0a3faa99b7388578d55eccecf272be4038 upstream

All memory accesses are done under some VQ mutex.
So lock/unlock all VQs is a faster equivalent of synchronize_rcu()
for memory access changes.
Some guests cause a lot of these changes, so it's helpful
to make them faster.

Reported-by: Gonglei (Arei) arei.gong...@huawei.com
Signed-off-by: Michael S. Tsirkin m...@redhat.com
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/vhost.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 78987e4..1c05e60 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -593,6 +593,7 @@ 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);
+   int i;
 
if (copy_from_user(mem, m, size))
return -EFAULT;
@@ -619,7 +620,14 @@ static long vhost_set_memory(struct vhost_dev *d, struct 
vhost_memory __user *m)
oldmem = rcu_dereference_protected(d-memory,
   lockdep_is_held(d-mutex));
rcu_assign_pointer(d-memory, newmem);
-   synchronize_rcu();
+
+   /* All memory accesses are done under some VQ mutex.
+* So below is a faster equivalent of synchronize_rcu()
+*/
+   for (i = 0; i  d-nvqs; ++i) {
+   mutex_lock(d-vqs[i]-mutex);
+   mutex_unlock(d-vqs[i]-mutex);
+   }
kfree(oldmem);
return 0;
 }
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 04/10] vhost/scsi: Add T10 PI IOV - SGL memory mapping logic

2014-08-20 Thread zhe.he
From: Nicholas Bellinger n...@linux-iscsi.org

commit e31885dd901e80d5bd528c1cbedde07ebbf051b2 upstream

This patch adds vhost_scsi_map_iov_to_prot() to perform the mapping of
T10 data integrity memory between virtio iov + struct scatterlist using
get_user_pages_fast() following existing code.

As with vhost_scsi_map_iov_to_sgl(), this does sanity checks against the
total prot_sgl_count vs. pre-allocated SGLs, and loops across protection
iovs using vhost_scsi_map_to_sgl() to perform the actual memory mapping.

Also update tcm_vhost_release_cmd() to release associated tvc_prot_sgl[]
struct page.

Cc: Michael S. Tsirkin m...@redhat.com
Cc: Paolo Bonzini pbonz...@redhat.com
Cc: Martin K. Petersen martin.peter...@oracle.com
Cc: Christoph Hellwig h...@lst.de
Cc: Hannes Reinecke h...@suse.de
Cc: Sagi Grimberg sa...@dev.mellanox.co.il
Cc: H. Peter Anvin h...@zytor.com
Acked-by: Michael S. Tsirkin m...@redhat.com
Signed-off-by: Nicholas Bellinger n...@linux-iscsi.org
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/scsi.c | 48 +++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 038fc5e..31d3b93 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -80,6 +80,7 @@ struct tcm_vhost_cmd {
u64 tvc_tag;
/* The number of scatterlists associated with this cmd */
u32 tvc_sgl_count;
+   u32 tvc_prot_sgl_count;
/* Saved unpacked SCSI LUN for tcm_vhost_submission_work() */
u32 tvc_lun;
/* Pointer to the SGL formatted memory from virtio-scsi */
@@ -458,12 +459,16 @@ static void tcm_vhost_release_cmd(struct se_cmd *se_cmd)
struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd,
struct tcm_vhost_cmd, tvc_se_cmd);
struct se_session *se_sess = se_cmd-se_sess;
+   int i;
 
if (tv_cmd-tvc_sgl_count) {
-   u32 i;
for (i = 0; i  tv_cmd-tvc_sgl_count; i++)
put_page(sg_page(tv_cmd-tvc_sgl[i]));
}
+   if (tv_cmd-tvc_prot_sgl_count) {
+   for (i = 0; i  tv_cmd-tvc_prot_sgl_count; i++)
+   put_page(sg_page(tv_cmd-tvc_prot_sgl[i]));
+   }
 
tcm_vhost_put_inflight(tv_cmd-inflight);
percpu_ida_free(se_sess-sess_tag_pool, se_cmd-map_tag);
@@ -856,6 +861,47 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
return 0;
 }
 
+static int
+vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd,
+  struct iovec *iov,
+  int niov,
+  bool write)
+{
+   struct scatterlist *prot_sg = cmd-tvc_prot_sgl;
+   unsigned int prot_sgl_count = 0;
+   int ret, i;
+
+   for (i = 0; i  niov; i++)
+   prot_sgl_count += iov_num_pages(iov[i]);
+
+   if (prot_sgl_count  TCM_VHOST_PREALLOC_PROT_SGLS) {
+   pr_err(vhost_scsi_map_iov_to_prot() sgl_count: %u greater than
+preallocated TCM_VHOST_PREALLOC_PROT_SGLS: %u\n,
+   prot_sgl_count, TCM_VHOST_PREALLOC_PROT_SGLS);
+   return -ENOBUFS;
+   }
+
+   pr_debug(%s prot_sg %p prot_sgl_count %u\n, __func__,
+prot_sg, prot_sgl_count);
+   sg_init_table(prot_sg, prot_sgl_count);
+   cmd-tvc_prot_sgl_count = prot_sgl_count;
+
+   for (i = 0; i  niov; i++) {
+   ret = vhost_scsi_map_to_sgl(cmd, prot_sg, prot_sgl_count, 
iov[i],
+   cmd-tvc_upages, write);
+   if (ret  0) {
+   for (i = 0; i  cmd-tvc_prot_sgl_count; i++)
+   put_page(sg_page(cmd-tvc_prot_sgl[i]));
+
+   cmd-tvc_prot_sgl_count = 0;
+   return ret;
+   }
+   prot_sg += ret;
+   prot_sgl_count -= ret;
+   }
+   return 0;
+}
+
 static void tcm_vhost_submission_work(struct work_struct *work)
 {
struct tcm_vhost_cmd *cmd =
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto


[linux-yocto] [PATCH 10/10] vhost-scsi: Include prot_bytes into expected data transfer length

2014-08-20 Thread zhe.he
From: Nicholas Bellinger n...@linux-iscsi.org

commit 9f977ef7b671f6169eca78bf40f230fe84b7c7e5 upstream

This patch updates vhost_scsi_get_tag() to accept the combined
expected data transfer length + T10 PI bytes as the value passed
into target_submit_cmd().

This is required now that target-core logic in commit 14ef9200
expects to subtract se_cmd-prot_length from se_cmd-data_length.

Cc: Paolo Bonzini pbonz...@redhat.com
Cc: Michael S. Tsirkin m...@redhat.com
Cc: Martin K. Petersen martin.peter...@oracle.com
Cc: Sagi Grimberg sa...@mellanox.com
Signed-off-by: Nicholas Bellinger n...@linux-iscsi.org
Signed-off-by: He Zhe zhe...@windriver.com
---
 drivers/vhost/scsi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 3671d65..6a52818 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1139,7 +1139,8 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct 
vhost_virtqueue *vq)
}
 
cmd = vhost_scsi_get_tag(vq, tpg, cdb, tag, lun, task_attr,
-exp_data_len, data_direction);
+exp_data_len + prot_bytes,
+data_direction);
if (IS_ERR(cmd)) {
vq_err(vq, vhost_scsi_get_tag failed %ld\n,
PTR_ERR(cmd));
-- 
1.9.1

-- 
___
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto