diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2013-09-19 19:48:39 +0530 |
---|---|---|
committer | Gary S. Robertson <gary.robertson@linaro.org> | 2013-10-24 09:37:02 -0500 |
commit | 5946d4b5ea5a009c712036a6ebcd540f40dd2cc4 (patch) | |
tree | c3addf79843084704692ca86ad7ed765e911460b | |
parent | 04cf4fc0d4a70bf75ac646f18c654cf019e96ef4 (diff) |
I found these files where there can be some issues on RT kernel:
- datapath/datapath.c
- datapath/vport.c
- datapath/linux/compat/workqueue.c
Important calls here are (that doesn't fit well with RT are):
- spin_lock_irq{save}()
- spin_lock_bh()
- local_bh_disable()
1- spin_lock_irq{save}()
These are simply converted to spin_lock() in RT and so access to critical
sections is guaranteed to be serialized.. And so nothing is required to be fixed
for it..
2- spin_lock_bh()
It guarantees code to be serialized and hence shouldn't be a problem..
2- local_bh_disable()
This is how it is implemented:
+void local_bh_disable(void)
+{
+ migrate_disable();
+ current->softirq_nestcnt++;
+}
+EXPORT_SYMBOL(local_bh_disable);
And here is the problem: Code currently using local_bh_disable() isn't
guaranteed to be serialized and so that is required to be fixed.
A simple solution would be to add a spin_lock_bh() for this case which will make
it work (efficiently) for both RT and non-RT cases.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r-- | datapath/actions.c | 5 | ||||
-rw-r--r-- | datapath/datapath.c | 2 |
2 files changed, 5 insertions, 2 deletions
diff --git a/datapath/actions.c b/datapath/actions.c index 30ea1d23..3550a00a 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -28,6 +28,7 @@ #include <linux/in6.h> #include <linux/if_arp.h> #include <linux/if_vlan.h> +#include <linux/spinlock.h> #include <net/ip.h> #include <net/ipv6.h> #include <net/checksum.h> @@ -38,6 +39,8 @@ #include "vlan.h" #include "vport.h" +static DEFINE_SPINLOCK(action_lock); + static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, const struct nlattr *attr, int len, bool keep_skb); @@ -600,6 +603,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb) int error; /* Check whether we've looped too much. */ + spin_lock_bh(&action_lock); loop = &__get_cpu_var(loop_counters); if (unlikely(++loop->count > MAX_LOOPS)) loop->looping = true; @@ -622,5 +626,6 @@ out_loop: if (!--loop->count) loop->looping = false; + spin_unlock_bh(&action_lock); return error; } diff --git a/datapath/datapath.c b/datapath/datapath.c index 50ee6cd3..6b7298a6 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -528,9 +528,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) if (!dp) goto err_unlock; - local_bh_disable(); err = ovs_execute_actions(dp, packet); - local_bh_enable(); rcu_read_unlock(); ovs_flow_free(flow, false); |