Phonet: put protocols array under RCU
[safe/jmp/linux-2.6] / net / phonet / af_phonet.c
index 8d3a55b..ed65da2 100644 (file)
@@ -35,7 +35,6 @@
 
 /* Transport protocol registration */
 static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly;
-static DEFINE_SPINLOCK(proto_tab_lock);
 
 static struct phonet_protocol *phonet_proto_get(int protocol)
 {
@@ -44,11 +43,11 @@ static struct phonet_protocol *phonet_proto_get(int protocol)
        if (protocol >= PHONET_NPROTO)
                return NULL;
 
-       spin_lock(&proto_tab_lock);
+       rcu_read_lock();
        pp = proto_tab[protocol];
        if (pp && !try_module_get(pp->prot->owner))
                pp = NULL;
-       spin_unlock(&proto_tab_lock);
+       rcu_read_unlock();
 
        return pp;
 }
@@ -439,6 +438,8 @@ static struct packet_type phonet_packet_type __read_mostly = {
        .func = phonet_rcv,
 };
 
+static DEFINE_MUTEX(proto_tab_lock);
+
 int __init_or_module phonet_proto_register(int protocol,
                                                struct phonet_protocol *pp)
 {
@@ -451,12 +452,12 @@ int __init_or_module phonet_proto_register(int protocol,
        if (err)
                return err;
 
-       spin_lock(&proto_tab_lock);
+       mutex_lock(&proto_tab_lock);
        if (proto_tab[protocol])
                err = -EBUSY;
        else
-               proto_tab[protocol] = pp;
-       spin_unlock(&proto_tab_lock);
+               rcu_assign_pointer(proto_tab[protocol], pp);
+       mutex_unlock(&proto_tab_lock);
 
        return err;
 }
@@ -464,10 +465,11 @@ EXPORT_SYMBOL(phonet_proto_register);
 
 void phonet_proto_unregister(int protocol, struct phonet_protocol *pp)
 {
-       spin_lock(&proto_tab_lock);
+       mutex_lock(&proto_tab_lock);
        BUG_ON(proto_tab[protocol] != pp);
-       proto_tab[protocol] = NULL;
-       spin_unlock(&proto_tab_lock);
+       rcu_assign_pointer(proto_tab[protocol], NULL);
+       mutex_unlock(&proto_tab_lock);
+       synchronize_rcu();
        proto_unregister(pp->prot);
 }
 EXPORT_SYMBOL(phonet_proto_unregister);