classifier: Make classifier_find_rule_exactly() lockless.
authorJarno Rajahalme <jrajahalme@nicira.com>
Mon, 3 Nov 2014 17:56:54 +0000 (09:56 -0800)
committerJarno Rajahalme <jrajahalme@nicira.com>
Thu, 6 Nov 2014 23:00:41 +0000 (15:00 -0800)
struct cls_match 'list' member was recently changed to an rculist.
This allows classifier_find_rule_exactly() to be made lockless.

Since subtable's 'max_priority' member would still require a lock, we
no longer check it before calling find_equal().  This adds a hash
table lookup in cases where the subtable may already be known to not
contain any rule of the target priority.
classifier_find_rule_exactly() is never called on the fastpath, so
this should not be significant.

Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
lib/classifier.c

index a4c99fa..251885d 100644 (file)
@@ -755,33 +755,26 @@ classifier_lookup(const struct classifier *cls, const struct flow *flow,
 const struct cls_rule *
 classifier_find_rule_exactly(const struct classifier *cls,
                              const struct cls_rule *target)
-    OVS_EXCLUDED(cls->mutex)
 {
     const struct cls_match *head, *rule;
     const struct cls_subtable *subtable;
 
-    ovs_mutex_lock(&cls->mutex);
     subtable = find_subtable(cls, &target->match.mask);
     if (!subtable) {
-        goto out;
-    }
-
-    /* Skip if there is no hope. */
-    if (target->priority > subtable->max_priority) {
-        goto out;
+        return NULL;
     }
 
     head = find_equal(subtable, &target->match.flow,
                       miniflow_hash_in_minimask(&target->match.flow,
                                                 &target->match.mask, 0));
+    if (!head) {
+        return NULL;
+    }
     FOR_EACH_RULE_IN_LIST (rule, head) {
         if (target->priority >= rule->priority) {
-            ovs_mutex_unlock(&cls->mutex);
             return target->priority == rule->priority ? rule->cls_rule : NULL;
         }
     }
-out:
-    ovs_mutex_unlock(&cls->mutex);
     return NULL;
 }