diff options
Diffstat (limited to 'net/phonet/af_phonet.c')
-rw-r--r-- | net/phonet/af_phonet.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 8d3a55b4a30c..ed65da251b6a 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c | |||
@@ -35,7 +35,6 @@ | |||
35 | 35 | ||
36 | /* Transport protocol registration */ | 36 | /* Transport protocol registration */ |
37 | static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly; | 37 | static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly; |
38 | static DEFINE_SPINLOCK(proto_tab_lock); | ||
39 | 38 | ||
40 | static struct phonet_protocol *phonet_proto_get(int protocol) | 39 | static struct phonet_protocol *phonet_proto_get(int protocol) |
41 | { | 40 | { |
@@ -44,11 +43,11 @@ static struct phonet_protocol *phonet_proto_get(int protocol) | |||
44 | if (protocol >= PHONET_NPROTO) | 43 | if (protocol >= PHONET_NPROTO) |
45 | return NULL; | 44 | return NULL; |
46 | 45 | ||
47 | spin_lock(&proto_tab_lock); | 46 | rcu_read_lock(); |
48 | pp = proto_tab[protocol]; | 47 | pp = proto_tab[protocol]; |
49 | if (pp && !try_module_get(pp->prot->owner)) | 48 | if (pp && !try_module_get(pp->prot->owner)) |
50 | pp = NULL; | 49 | pp = NULL; |
51 | spin_unlock(&proto_tab_lock); | 50 | rcu_read_unlock(); |
52 | 51 | ||
53 | return pp; | 52 | return pp; |
54 | } | 53 | } |
@@ -439,6 +438,8 @@ static struct packet_type phonet_packet_type __read_mostly = { | |||
439 | .func = phonet_rcv, | 438 | .func = phonet_rcv, |
440 | }; | 439 | }; |
441 | 440 | ||
441 | static DEFINE_MUTEX(proto_tab_lock); | ||
442 | |||
442 | int __init_or_module phonet_proto_register(int protocol, | 443 | int __init_or_module phonet_proto_register(int protocol, |
443 | struct phonet_protocol *pp) | 444 | struct phonet_protocol *pp) |
444 | { | 445 | { |
@@ -451,12 +452,12 @@ int __init_or_module phonet_proto_register(int protocol, | |||
451 | if (err) | 452 | if (err) |
452 | return err; | 453 | return err; |
453 | 454 | ||
454 | spin_lock(&proto_tab_lock); | 455 | mutex_lock(&proto_tab_lock); |
455 | if (proto_tab[protocol]) | 456 | if (proto_tab[protocol]) |
456 | err = -EBUSY; | 457 | err = -EBUSY; |
457 | else | 458 | else |
458 | proto_tab[protocol] = pp; | 459 | rcu_assign_pointer(proto_tab[protocol], pp); |
459 | spin_unlock(&proto_tab_lock); | 460 | mutex_unlock(&proto_tab_lock); |
460 | 461 | ||
461 | return err; | 462 | return err; |
462 | } | 463 | } |
@@ -464,10 +465,11 @@ EXPORT_SYMBOL(phonet_proto_register); | |||
464 | 465 | ||
465 | void phonet_proto_unregister(int protocol, struct phonet_protocol *pp) | 466 | void phonet_proto_unregister(int protocol, struct phonet_protocol *pp) |
466 | { | 467 | { |
467 | spin_lock(&proto_tab_lock); | 468 | mutex_lock(&proto_tab_lock); |
468 | BUG_ON(proto_tab[protocol] != pp); | 469 | BUG_ON(proto_tab[protocol] != pp); |
469 | proto_tab[protocol] = NULL; | 470 | rcu_assign_pointer(proto_tab[protocol], NULL); |
470 | spin_unlock(&proto_tab_lock); | 471 | mutex_unlock(&proto_tab_lock); |
472 | synchronize_rcu(); | ||
471 | proto_unregister(pp->prot); | 473 | proto_unregister(pp->prot); |
472 | } | 474 | } |
473 | EXPORT_SYMBOL(phonet_proto_unregister); | 475 | EXPORT_SYMBOL(phonet_proto_unregister); |