X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Fflow.c;h=dfbf76938e0c8f7d1979384b8b0adcb1048318f9;hb=fb8c93473efacd67a50117d0f2a3084f2d96ceca;hp=1f01166c5ef86d2cb842dbdda316b4f5293ae1a0;hpb=560e802229f3028c02273435dd1c6efba33e0949;p=sliver-openvswitch.git diff --git a/datapath/flow.c b/datapath/flow.c index 1f01166c5..dfbf76938 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -132,36 +132,27 @@ struct sw_flow *flow_alloc(void) return ERR_PTR(-ENOMEM); spin_lock_init(&flow->lock); + atomic_set(&flow->refcnt, 1); + flow->dead = false; return flow; } -void flow_free(struct sw_flow *flow) -{ - if (unlikely(!flow)) - return; - - kmem_cache_free(flow_cache, flow); -} - -/* Frees the entire 'flow' (both base and actions) immediately. */ -static void flow_free_full(struct sw_flow *flow) -{ - kfree(flow->sf_acts); - flow_free(flow); -} - void flow_free_tbl(struct tbl_node *node) { struct sw_flow *flow = flow_cast(node); - flow_free_full(flow); + + flow->dead = true; + flow_put(flow); } /* RCU callback used by flow_deferred_free. */ static void rcu_free_flow_callback(struct rcu_head *rcu) { struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu); - flow_free_full(flow); + + flow->dead = true; + flow_put(flow); } /* Schedules 'flow' to be freed after the next RCU grace period. @@ -171,6 +162,22 @@ void flow_deferred_free(struct sw_flow *flow) call_rcu(&flow->rcu, rcu_free_flow_callback); } +void flow_hold(struct sw_flow *flow) +{ + atomic_inc(&flow->refcnt); +} + +void flow_put(struct sw_flow *flow) +{ + if (unlikely(!flow)) + return; + + if (atomic_dec_and_test(&flow->refcnt)) { + kfree(flow->sf_acts); + kmem_cache_free(flow_cache, flow); + } +} + /* RCU callback used by flow_deferred_free_acts. */ static void rcu_free_acts_callback(struct rcu_head *rcu) {