diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-15 01:33:11 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-11-15 01:33:11 -0500 |
commit | 1bb95834bbcdc969e477a9284cf96c17a4c2616f (patch) | |
tree | 9cf66b22a611bb6bc78778c05dac72263bb45a23 /net/core/fib_rules.c | |
parent | 85345517fe6d4de27b0d6ca19fef9d28ac947c4a (diff) | |
parent | a41c73e04673b47730df682446f0d52f95e32a5b (diff) |
Merge remote branch 'airlied/drm-fixes' into drm-intel-fixes
Diffstat (limited to 'net/core/fib_rules.c')
-rw-r--r-- | net/core/fib_rules.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 1bc3f253ba6c..82a4369ae150 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -351,12 +351,12 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
351 | 351 | ||
352 | list_for_each_entry(r, &ops->rules_list, list) { | 352 | list_for_each_entry(r, &ops->rules_list, list) { |
353 | if (r->pref == rule->target) { | 353 | if (r->pref == rule->target) { |
354 | rule->ctarget = r; | 354 | RCU_INIT_POINTER(rule->ctarget, r); |
355 | break; | 355 | break; |
356 | } | 356 | } |
357 | } | 357 | } |
358 | 358 | ||
359 | if (rule->ctarget == NULL) | 359 | if (rcu_dereference_protected(rule->ctarget, 1) == NULL) |
360 | unresolved = 1; | 360 | unresolved = 1; |
361 | } else if (rule->action == FR_ACT_GOTO) | 361 | } else if (rule->action == FR_ACT_GOTO) |
362 | goto errout_free; | 362 | goto errout_free; |
@@ -373,6 +373,11 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
373 | 373 | ||
374 | fib_rule_get(rule); | 374 | fib_rule_get(rule); |
375 | 375 | ||
376 | if (last) | ||
377 | list_add_rcu(&rule->list, &last->list); | ||
378 | else | ||
379 | list_add_rcu(&rule->list, &ops->rules_list); | ||
380 | |||
376 | if (ops->unresolved_rules) { | 381 | if (ops->unresolved_rules) { |
377 | /* | 382 | /* |
378 | * There are unresolved goto rules in the list, check if | 383 | * There are unresolved goto rules in the list, check if |
@@ -381,7 +386,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
381 | list_for_each_entry(r, &ops->rules_list, list) { | 386 | list_for_each_entry(r, &ops->rules_list, list) { |
382 | if (r->action == FR_ACT_GOTO && | 387 | if (r->action == FR_ACT_GOTO && |
383 | r->target == rule->pref) { | 388 | r->target == rule->pref) { |
384 | BUG_ON(r->ctarget != NULL); | 389 | BUG_ON(rtnl_dereference(r->ctarget) != NULL); |
385 | rcu_assign_pointer(r->ctarget, rule); | 390 | rcu_assign_pointer(r->ctarget, rule); |
386 | if (--ops->unresolved_rules == 0) | 391 | if (--ops->unresolved_rules == 0) |
387 | break; | 392 | break; |
@@ -395,11 +400,6 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
395 | if (unresolved) | 400 | if (unresolved) |
396 | ops->unresolved_rules++; | 401 | ops->unresolved_rules++; |
397 | 402 | ||
398 | if (last) | ||
399 | list_add_rcu(&rule->list, &last->list); | ||
400 | else | ||
401 | list_add_rcu(&rule->list, &ops->rules_list); | ||
402 | |||
403 | notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid); | 403 | notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid); |
404 | flush_route_cache(ops); | 404 | flush_route_cache(ops); |
405 | rules_ops_put(ops); | 405 | rules_ops_put(ops); |
@@ -487,7 +487,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
487 | */ | 487 | */ |
488 | if (ops->nr_goto_rules > 0) { | 488 | if (ops->nr_goto_rules > 0) { |
489 | list_for_each_entry(tmp, &ops->rules_list, list) { | 489 | list_for_each_entry(tmp, &ops->rules_list, list) { |
490 | if (tmp->ctarget == rule) { | 490 | if (rtnl_dereference(tmp->ctarget) == rule) { |
491 | rcu_assign_pointer(tmp->ctarget, NULL); | 491 | rcu_assign_pointer(tmp->ctarget, NULL); |
492 | ops->unresolved_rules++; | 492 | ops->unresolved_rules++; |
493 | } | 493 | } |
@@ -545,7 +545,8 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, | |||
545 | frh->action = rule->action; | 545 | frh->action = rule->action; |
546 | frh->flags = rule->flags; | 546 | frh->flags = rule->flags; |
547 | 547 | ||
548 | if (rule->action == FR_ACT_GOTO && rule->ctarget == NULL) | 548 | if (rule->action == FR_ACT_GOTO && |
549 | rcu_dereference_raw(rule->ctarget) == NULL) | ||
549 | frh->flags |= FIB_RULE_UNRESOLVED; | 550 | frh->flags |= FIB_RULE_UNRESOLVED; |
550 | 551 | ||
551 | if (rule->iifname[0]) { | 552 | if (rule->iifname[0]) { |