diff options
| author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-07-07 09:41:29 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-07-07 09:41:29 -0400 |
| commit | afe62c68cd3562c5f8e3ea293e82906dd5a87936 (patch) | |
| tree | 5cc472bb610de783a1dca1e9f54043a0918d60bd /net/packet | |
| parent | 68ac31918ec359a2bfb9f897bb62c2940652d2b8 (diff) | |
af_packet: lock imbalance
fanout_add() might return with fanout_mutex held.
Reduce indentation level while we are at it
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/packet')
| -rw-r--r-- | net/packet/af_packet.c | 62 |
1 files changed, 31 insertions, 31 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index aec50a1e984..aa4c73afa19 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -589,43 +589,43 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) | |||
| 589 | break; | 589 | break; |
| 590 | } | 590 | } |
| 591 | } | 591 | } |
| 592 | err = -EINVAL; | ||
| 592 | if (match && match->defrag != defrag) | 593 | if (match && match->defrag != defrag) |
| 593 | return -EINVAL; | 594 | goto out; |
| 594 | if (!match) { | 595 | if (!match) { |
| 596 | err = -ENOMEM; | ||
| 595 | match = kzalloc(sizeof(*match), GFP_KERNEL); | 597 | match = kzalloc(sizeof(*match), GFP_KERNEL); |
| 596 | if (match) { | 598 | if (!match) |
| 597 | write_pnet(&match->net, sock_net(sk)); | 599 | goto out; |
| 598 | match->id = id; | 600 | write_pnet(&match->net, sock_net(sk)); |
| 599 | match->type = type; | 601 | match->id = id; |
| 600 | match->defrag = defrag; | 602 | match->type = type; |
| 601 | atomic_set(&match->rr_cur, 0); | 603 | match->defrag = defrag; |
| 602 | INIT_LIST_HEAD(&match->list); | 604 | atomic_set(&match->rr_cur, 0); |
| 603 | spin_lock_init(&match->lock); | 605 | INIT_LIST_HEAD(&match->list); |
| 604 | atomic_set(&match->sk_ref, 0); | 606 | spin_lock_init(&match->lock); |
| 605 | match->prot_hook.type = po->prot_hook.type; | 607 | atomic_set(&match->sk_ref, 0); |
| 606 | match->prot_hook.dev = po->prot_hook.dev; | 608 | match->prot_hook.type = po->prot_hook.type; |
| 607 | match->prot_hook.func = packet_rcv_fanout; | 609 | match->prot_hook.dev = po->prot_hook.dev; |
| 608 | match->prot_hook.af_packet_priv = match; | 610 | match->prot_hook.func = packet_rcv_fanout; |
| 609 | dev_add_pack(&match->prot_hook); | 611 | match->prot_hook.af_packet_priv = match; |
| 610 | list_add(&match->list, &fanout_list); | 612 | dev_add_pack(&match->prot_hook); |
| 611 | } | 613 | list_add(&match->list, &fanout_list); |
| 612 | } | 614 | } |
| 613 | err = -ENOMEM; | 615 | err = -EINVAL; |
| 614 | if (match) { | 616 | if (match->type == type && |
| 615 | err = -EINVAL; | 617 | match->prot_hook.type == po->prot_hook.type && |
| 616 | if (match->type == type && | 618 | match->prot_hook.dev == po->prot_hook.dev) { |
| 617 | match->prot_hook.type == po->prot_hook.type && | 619 | err = -ENOSPC; |
| 618 | match->prot_hook.dev == po->prot_hook.dev) { | 620 | if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) { |
| 619 | err = -ENOSPC; | 621 | __dev_remove_pack(&po->prot_hook); |
| 620 | if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) { | 622 | po->fanout = match; |
| 621 | __dev_remove_pack(&po->prot_hook); | 623 | atomic_inc(&match->sk_ref); |
| 622 | po->fanout = match; | 624 | __fanout_link(sk, po); |
| 623 | atomic_inc(&match->sk_ref); | 625 | err = 0; |
| 624 | __fanout_link(sk, po); | ||
| 625 | err = 0; | ||
| 626 | } | ||
| 627 | } | 626 | } |
| 628 | } | 627 | } |
| 628 | out: | ||
| 629 | mutex_unlock(&fanout_mutex); | 629 | mutex_unlock(&fanout_mutex); |
| 630 | return err; | 630 | return err; |
| 631 | } | 631 | } |
