Alex,

Not a review, but a comment: Isn’t it unnecessary to use atomics when the 
refcount is protected with a mutex?

Also, in general, a thread should not release the last reference if other 
threads can still find the object. Why does this happen here?

  Jarno

> On Jul 16, 2015, at 3:48 PM, Alex Wang <al...@nicira.com> wrote:
> 
> In ovs 2.1, the unref functions for ipfix and sflow are called
> in ofproto/ofproto-dpif-upcall.c without the protection of
> any lock.  If the unprotected call of unref function removes
> the last reference, and at the same time, other thread is
> trying to ref the same struct, the race could cause abortion
> of ovs.
> 
> To fix this issue, this commit protects the ref and unref
> functions using the global mutex of the ipfix and sflow
> modules respectively.
> 
> Reported-by: Xiao Ma <cumtb_max...@163.com>
> Signed-off-by: Alex Wang <al...@nicira.com>
> ---
> ofproto/ofproto-dpif-ipfix.c |    6 ++++--
> ofproto/ofproto-dpif-sflow.c |   14 +++++---------
> 2 files changed, 9 insertions(+), 11 deletions(-)
> 
> diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c
> index a9cc73e..8deace8 100644
> --- a/ofproto/ofproto-dpif-ipfix.c
> +++ b/ofproto/ofproto-dpif-ipfix.c
> @@ -647,11 +647,13 @@ struct dpif_ipfix *
> dpif_ipfix_ref(const struct dpif_ipfix *di_)
> {
>     struct dpif_ipfix *di = CONST_CAST(struct dpif_ipfix *, di_);
> +    ovs_mutex_lock(&mutex);
>     if (di) {
>         int orig;
>         atomic_add(&di->ref_cnt, 1, &orig);
>         ovs_assert(orig > 0);
>     }
> +    ovs_mutex_unlock(&mutex);
>     return di;
> }
> 
> @@ -689,16 +691,16 @@ dpif_ipfix_unref(struct dpif_ipfix *di) 
> OVS_EXCLUDED(mutex)
>         return;
>     }
> 
> +    ovs_mutex_lock(&mutex);
>     atomic_sub(&di->ref_cnt, 1, &orig);
>     ovs_assert(orig > 0);
>     if (orig == 1) {
> -        ovs_mutex_lock(&mutex);
>         dpif_ipfix_clear(di);
>         dpif_ipfix_bridge_exporter_destroy(&di->bridge_exporter);
>         hmap_destroy(&di->flow_exporter_map);
>         free(di);
> -        ovs_mutex_unlock(&mutex);
>     }
> +    ovs_mutex_unlock(&mutex);
> }
> 
> static void
> diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
> index 158887f..07a5c4b 100644
> --- a/ofproto/ofproto-dpif-sflow.c
> +++ b/ofproto/ofproto-dpif-sflow.c
> @@ -292,14 +292,6 @@ dpif_sflow_clear__(struct dpif_sflow *ds) 
> OVS_REQUIRES(mutex)
>     ds->probability = 0;
> }
> 
> -void
> -dpif_sflow_clear(struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
> -{
> -    ovs_mutex_lock(&mutex);
> -    dpif_sflow_clear__(ds);
> -    ovs_mutex_unlock(&mutex);
> -}
> -
> bool
> dpif_sflow_is_enabled(const struct dpif_sflow *ds) OVS_EXCLUDED(mutex)
> {
> @@ -336,11 +328,13 @@ struct dpif_sflow *
> dpif_sflow_ref(const struct dpif_sflow *ds_)
> {
>     struct dpif_sflow *ds = CONST_CAST(struct dpif_sflow *, ds_);
> +    ovs_mutex_lock(&mutex);
>     if (ds) {
>         int orig;
>         atomic_add(&ds->ref_cnt, 1, &orig);
>         ovs_assert(orig > 0);
>     }
> +    ovs_mutex_unlock(&mutex);
>     return ds;
> }
> 
> @@ -366,19 +360,21 @@ dpif_sflow_unref(struct dpif_sflow *ds) 
> OVS_EXCLUDED(mutex)
>         return;
>     }
> 
> +    ovs_mutex_lock(&mutex);
>     atomic_sub(&ds->ref_cnt, 1, &orig);
>     ovs_assert(orig > 0);
>     if (orig == 1) {
>         struct dpif_sflow_port *dsp, *next;
> 
>         route_table_unregister();
> -        dpif_sflow_clear(ds);
> +        dpif_sflow_clear__(ds);
>         HMAP_FOR_EACH_SAFE (dsp, next, hmap_node, &ds->ports) {
>             dpif_sflow_del_port__(ds, dsp);
>         }
>         hmap_destroy(&ds->ports);
>         free(ds);
>     }
> +    ovs_mutex_unlock(&mutex);
> }
> 
> static void
> -- 
> 1.7.9.5
> 
> _______________________________________________
> 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