2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-17 14:28:02 +00:00

rculist: Remove postponed poisoning.

Postponed 'next' member poisoning was based on the faulty assumption
that postponed functions would be called in the order they were
postponed.  This assumption holds only for the functions postponed by
any single thread.  When functions are postponed by different
threads, there are no guarantees of the order in which the functions
may be called, or timing between those calls after the next grace
period has passed.

Given this, the postponed poisoning could have executed after
postponed destruction of the object containing the rculist element.

This bug was revealed after the memory leaks on rule deletion were
recently fixed.

This patch removes the postponed 'next' member poisoning and adds
documentation describing the ordering limitations in OVS RCU.

Alex Wang dug out the root cause of the resulting crashes, thanks!

Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Alex Wang <alexw@nicira.com>
This commit is contained in:
Jarno Rajahalme
2015-06-11 17:28:37 -07:00
parent e815de429c
commit 2541d75983
6 changed files with 48 additions and 52 deletions

View File

@@ -241,14 +241,14 @@ cls_rule_move(struct cls_rule *dst, struct cls_rule *src)
* ('rule' must not currently be in a classifier.) */
void
cls_rule_destroy(struct cls_rule *rule)
OVS_NO_THREAD_SAFETY_ANALYSIS
{
ovs_assert(!rule->cls_match); /* Must not be in a classifier. */
/* Check that the rule has been properly removed from the classifier and
* that the destruction only happens after the RCU grace period, or that
* the rule was never inserted to the classifier in the first place. */
ovs_assert(rculist_next_protected(&rule->node) == RCULIST_POISON
/* Check that the rule has been properly removed from the classifier. */
ovs_assert(rule->node.prev == RCULIST_POISON
|| rculist_is_empty(&rule->node));
rculist_poison__(&rule->node); /* Poisons also the next pointer. */
minimatch_destroy(CONST_CAST(struct minimatch *, &rule->match));
}