aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/flow_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/openvswitch/flow_table.c')
-rw-r--r--net/openvswitch/flow_table.c44
1 files changed, 25 insertions, 19 deletions
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index d8ef37b937bd..c80df6f42fee 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)
159 if (!flow) 159 if (!flow)
160 return; 160 return;
161 161
162 if (flow->mask) {
163 struct sw_flow_mask *mask = flow->mask;
164
165 /* ovs-lock is required to protect mask-refcount and
166 * mask list.
167 */
168 ASSERT_OVSL();
169 BUG_ON(!mask->ref_count);
170 mask->ref_count--;
171
172 if (!mask->ref_count) {
173 list_del_rcu(&mask->list);
174 if (deferred)
175 kfree_rcu(mask, rcu);
176 else
177 kfree(mask);
178 }
179 }
180
181 if (deferred) 162 if (deferred)
182 call_rcu(&flow->rcu, rcu_free_flow_callback); 163 call_rcu(&flow->rcu, rcu_free_flow_callback);
183 else 164 else
@@ -491,6 +472,25 @@ static struct table_instance *table_instance_expand(struct table_instance *ti)
491 return table_instance_rehash(ti, ti->n_buckets * 2); 472 return table_instance_rehash(ti, ti->n_buckets * 2);
492} 473}
493 474
475/* Remove 'mask' from the mask list, if it is not needed any more. */
476static void flow_mask_remove(struct flow_table *tbl, struct sw_flow_mask *mask)
477{
478 if (mask) {
479 /* ovs-lock is required to protect mask-refcount and
480 * mask list.
481 */
482 ASSERT_OVSL();
483 BUG_ON(!mask->ref_count);
484 mask->ref_count--;
485
486 if (!mask->ref_count) {
487 list_del_rcu(&mask->list);
488 kfree_rcu(mask, rcu);
489 }
490 }
491}
492
493/* Must be called with OVS mutex held. */
494void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow) 494void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
495{ 495{
496 struct table_instance *ti = ovsl_dereference(table->ti); 496 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)
498 BUG_ON(table->count == 0); 498 BUG_ON(table->count == 0);
499 hlist_del_rcu(&flow->hash_node[ti->node_ver]); 499 hlist_del_rcu(&flow->hash_node[ti->node_ver]);
500 table->count--; 500 table->count--;
501
502 /* RCU delete the mask. 'flow->mask' is not NULLed, as it should be
503 * accessible as long as the RCU read lock is held.
504 */
505 flow_mask_remove(table, flow->mask);
501} 506}
502 507
503static struct sw_flow_mask *mask_alloc(void) 508static struct sw_flow_mask *mask_alloc(void)
@@ -560,6 +565,7 @@ static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
560 return 0; 565 return 0;
561} 566}
562 567
568/* Must be called with OVS mutex held. */
563int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow, 569int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
564 struct sw_flow_mask *mask) 570 struct sw_flow_mask *mask)
565{ 571{