Bluetooth: Convert inquiry cache to use debugfs instead of sysfs
[safe/jmp/linux-2.6] / net / core / fib_rules.c
index d1a70ad..9a24377 100644 (file)
@@ -72,7 +72,7 @@ static void flush_route_cache(struct fib_rules_ops *ops)
                ops->flush_cache(ops);
 }
 
-int fib_rules_register(struct fib_rules_ops *ops)
+static int __fib_rules_register(struct fib_rules_ops *ops)
 {
        int err = -EEXIST;
        struct fib_rules_ops *o;
@@ -102,6 +102,28 @@ errout:
        return err;
 }
 
+struct fib_rules_ops *
+fib_rules_register(struct fib_rules_ops *tmpl, struct net *net)
+{
+       struct fib_rules_ops *ops;
+       int err;
+
+       ops = kmemdup(tmpl, sizeof (*ops), GFP_KERNEL);
+       if (ops == NULL)
+               return ERR_PTR(-ENOMEM);
+
+       INIT_LIST_HEAD(&ops->rules_list);
+       ops->fro_net = net;
+
+       err = __fib_rules_register(ops);
+       if (err) {
+               kfree(ops);
+               ops = ERR_PTR(err);
+       }
+
+       return ops;
+}
+
 EXPORT_SYMBOL_GPL(fib_rules_register);
 
 void fib_rules_cleanup_ops(struct fib_rules_ops *ops)
@@ -115,6 +137,15 @@ void fib_rules_cleanup_ops(struct fib_rules_ops *ops)
 }
 EXPORT_SYMBOL_GPL(fib_rules_cleanup_ops);
 
+static void fib_rules_put_rcu(struct rcu_head *head)
+{
+       struct fib_rules_ops *ops = container_of(head, struct fib_rules_ops, rcu);
+       struct net *net = ops->fro_net;
+
+       release_net(net);
+       kfree(ops);
+}
+
 void fib_rules_unregister(struct fib_rules_ops *ops)
 {
        struct net *net = ops->fro_net;
@@ -124,8 +155,7 @@ void fib_rules_unregister(struct fib_rules_ops *ops)
        fib_rules_cleanup_ops(ops);
        spin_unlock(&net->rules_mod_lock);
 
-       synchronize_rcu();
-       release_net(net);
+       call_rcu(&ops->rcu, fib_rules_put_rcu);
 }
 
 EXPORT_SYMBOL_GPL(fib_rules_unregister);
@@ -287,7 +317,7 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
        rule->flags = frh->flags;
        rule->table = frh_get_table(frh, tb);
 
-       if (!rule->pref && ops->default_pref)
+       if (!tb[FRA_PRIORITY] && ops->default_pref)
                rule->pref = ops->default_pref(ops);
 
        err = -EINVAL;
@@ -678,7 +708,7 @@ static struct notifier_block fib_rules_notifier = {
        .notifier_call = fib_rules_event,
 };
 
-static int fib_rules_net_init(struct net *net)
+static int __net_init fib_rules_net_init(struct net *net)
 {
        INIT_LIST_HEAD(&net->rules_ops);
        spin_lock_init(&net->rules_mod_lock);