On Tue, Mar 25, 2014 at 2:35 PM, Jarno Rajahalme <jrajaha...@nicira.com> wrote:
> 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.
>
After looking at this patch and last one, it looks like we are doing
log more work just to make RCU checker happy.
Can we just use rcu_read_lock() and unlock() to protect acts de-referencing ?

> Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
> ---
> v5: Split to a separate patch, relaxed locking requirements.
>
>  datapath/datapath.c |   58 
> ++++++++++++++++++++++++++++++++-------------------
>  datapath/flow.c     |    6 ++++--
>  datapath/flow.h     |    2 +-
>  3 files changed, 41 insertions(+), 25 deletions(-)
>
> diff --git a/datapath/datapath.c b/datapath/datapath.c
> index d1b0155..01913f6 100644
> --- a/datapath/datapath.c
> +++ b/datapath/datapath.c
> @@ -663,8 +663,17 @@ 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 or RCU read lock. */
> -static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
> +/* Allow a flow to be accessed if:
> + * - RCU read lock is held, or
> + * - OVS mutex is held, or
> + * - the flow has already been removed from the flow table. */
> +#define ovsl_dereference_flow_acts(flow)                               \
> +       rcu_dereference_check(flow->sf_acts, (lockdep_ovsl_is_held()    \
> +                                             || ovs_flow_removed(flow)))
> +
> +/* Must be called with rcu_read_lock or ovs_mutex if 'flow' is in the flow
> + * table. */
> +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)
>  {
> @@ -681,7 +690,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);
> @@ -730,8 +739,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, 
> struct datapath *dp,
>         if (start) {
>                 const struct sw_flow_actions *sf_acts;
>
> -               sf_acts = rcu_dereference_ovsl(flow->sf_acts);
> -
> +               sf_acts = ovsl_dereference_flow_acts(flow);
>                 err = ovs_nla_put_actions(sf_acts->actions,
>                                           sf_acts->actions_len, skb);
>                 if (!err)
> @@ -754,8 +762,9 @@ error:
>         return err;
>  }
>
> -/* Must be called with ovs_mutex. */
> -static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow,
> +/* Must be called with rcu_read_lock or ovs_mutex if 'flow' is in the flow
> + * table. */
> +static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow *flow,
>                                                struct genl_info *info,
>                                                bool always)
>  {
> @@ -765,7 +774,7 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(struct 
> sw_flow *flow,
>         if (!always && !ovs_must_notify(info, &ovs_dp_flow_multicast_group))
>                 return NULL;
>
> -       len = ovs_flow_cmd_msg_size(ovsl_dereference(flow->sf_acts));
> +       len = ovs_flow_cmd_msg_size(ovsl_dereference_flow_acts(flow));
>
>         skb = genlmsg_new_unicast(len, info, GFP_KERNEL);
>
> @@ -775,11 +784,12 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(struct 
> sw_flow *flow,
>         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)
> +/* Must be called with rcu_read_lock or ovs_mutex if 'flow' is in the flow
> + * table. */
> +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;
> @@ -788,8 +798,9 @@ static struct sk_buff *ovs_flow_cmd_build_info(struct 
> sw_flow *flow,
>         if (!skb || IS_ERR(skb))
>                 return skb;
>
> -       retval = ovs_flow_cmd_fill_info(flow, dp, skb, info->snd_portid,
> -                                       info->snd_seq, 0, cmd);
> +       retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb,
> +                                       info->snd_portid, info->snd_seq, 0,
> +                                       cmd);
>         BUG_ON(retval < 0);
>         return skb;
>  }
> @@ -870,8 +881,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, false);
> +               reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
> +                                               info, OVS_FLOW_CMD_NEW, 
> false);
>         } else {
>                 /* We found a matching flow. */
>                 /* Bail out if we're not allowed to modify an existing flow.
> @@ -897,8 +908,9 @@ 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, false);
> +
> +               reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
> +                                               info, OVS_FLOW_CMD_NEW, 
> false);
>
>                 /* Clear stats. */
>                 if (a[OVS_FLOW_ATTR_CLEAR])
> @@ -960,7 +972,8 @@ 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, 
> true);
> +       reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex, info,
> +                                       OVS_FLOW_CMD_NEW, true);
>         if (IS_ERR(reply)) {
>                 err = PTR_ERR(reply);
>                 goto unlock;
> @@ -1016,7 +1029,8 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct 
> genl_info *info)
>         ovs_flow_tbl_remove(&dp->table, flow);
>
>         if (reply) {
> -               err = ovs_flow_cmd_fill_info(flow, dp, reply, 
> info->snd_portid,
> +               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);
> @@ -1057,7 +1071,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, 
> struct netlink_callback *cb)
>                 if (!flow)
>                         break;
>
> -               if (ovs_flow_cmd_fill_info(flow, dp, skb,
> +               if (ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex, skb,
>                                            NETLINK_CB(cb->skb).portid,
>                                            cb->nlh->nlmsg_seq, NLM_F_MULTI,
>                                            OVS_FLOW_CMD_NEW) < 0)
> diff --git a/datapath/flow.c b/datapath/flow.c
> index 5d1d2f2..6d7c3b5 100644
> --- a/datapath/flow.c
> +++ b/datapath/flow.c
> @@ -123,8 +123,10 @@ 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 if 'flow' is in the flow
> + * table. */
> +void ovs_flow_stats_get(const struct sw_flow *flow,
> +                       struct ovs_flow_stats *ovs_stats,
>                         unsigned long *used, __be16 *tcp_flags)
>  {
>         int node;
> diff --git a/datapath/flow.h b/datapath/flow.h
> index 5587577..25eba04 100644
> --- a/datapath/flow.h
> +++ b/datapath/flow.h
> @@ -183,7 +183,7 @@ struct arp_eth_header {
>  } __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_get(const struct sw_flow *, struct ovs_flow_stats *,
>                         unsigned long *used, __be16 *tcp_flags);
>  void ovs_flow_stats_clear(struct sw_flow *flow);
>  u64 ovs_flow_used_time(unsigned long flow_jiffies);
> --
> 1.7.10.4
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to