aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/flow_table.c
diff options
context:
space:
mode:
authorJarno Rajahalme <jrajahalme@nicira.com>2014-05-05 16:24:53 -0400
committerPravin B Shelar <pshelar@nicira.com>2014-05-22 19:27:35 -0400
commit56c19868e115fcf8d62d843e1b9616bb9837d0db (patch)
treea013eb4d440cfc874332eb3120595e6b0c9976d8 /net/openvswitch/flow_table.c
parentfb5d1e9e127ad1542e5db20cd8620a1509baef69 (diff)
openvswitch: Make flow mask removal symmetric.
Masks are inserted when flows are inserted to the table, so it is logical to correspondingly remove masks when flows are removed from the table, in ovs_flow_table_remove(). This allows ovs_flow_free() to be called without locking, which will be used by later patches. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
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{