diff options
author | Tonghao Zhang <xiangxia.m.yue@gmail.com> | 2019-11-01 22:23:47 +0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-11-03 17:18:03 -0800 |
commit | 1689754de624a19e37a2f96289f4421466771687 (patch) | |
tree | b4c649d18ffa936d68eff22195874761052a5d56 /net/openvswitch | |
parent | 4bc63b1b531df518576a97d17bf5939fdbc33ccb (diff) | |
download | linux-stable-1689754de624a19e37a2f96289f4421466771687.tar.gz linux-stable-1689754de624a19e37a2f96289f4421466771687.tar.bz2 linux-stable-1689754de624a19e37a2f96289f4421466771687.zip |
net: openvswitch: shrink the mask array if necessary
When creating and inserting flow-mask, if there is no available
flow-mask, we realloc the mask array. When removing flow-mask,
if necessary, we shrink mask array.
Signed-off-by: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Tested-by: Greg Rose <gvrose8192@gmail.com>
Acked-by: William Tu <u9012063@gmail.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r-- | net/openvswitch/flow_table.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index 92efa232d764..0c0fcd644122 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c @@ -694,6 +694,23 @@ static struct table_instance *table_instance_expand(struct table_instance *ti, return table_instance_rehash(ti, ti->n_buckets * 2, ufid); } +static void tbl_mask_array_delete_mask(struct mask_array *ma, + struct sw_flow_mask *mask) +{ + int i; + + /* Remove the deleted mask pointers from the array */ + for (i = 0; i < ma->max; i++) { + if (mask == ovsl_dereference(ma->masks[i])) { + RCU_INIT_POINTER(ma->masks[i], NULL); + ma->count--; + kfree_rcu(mask, rcu); + return; + } + } + BUG(); +} + /* Remove 'mask' from the mask list, if it is not needed any more. */ static void flow_mask_remove(struct flow_table *tbl, struct sw_flow_mask *mask) { @@ -707,18 +724,14 @@ static void flow_mask_remove(struct flow_table *tbl, struct sw_flow_mask *mask) if (!mask->ref_count) { struct mask_array *ma; - int i; ma = ovsl_dereference(tbl->mask_array); - for (i = 0; i < ma->max; i++) { - if (mask == ovsl_dereference(ma->masks[i])) { - RCU_INIT_POINTER(ma->masks[i], NULL); - ma->count--; - kfree_rcu(mask, rcu); - return; - } - } - BUG(); + tbl_mask_array_delete_mask(ma, mask); + + /* Shrink the mask array if necessary. */ + if (ma->max >= (MASK_ARRAY_SIZE_MIN * 2) && + ma->count <= (ma->max / 3)) + tbl_mask_array_realloc(tbl, ma->max / 2); } } } |