aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-07-07 09:41:29 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-07 09:41:29 -0400
commitafe62c68cd3562c5f8e3ea293e82906dd5a87936 (patch)
tree5cc472bb610de783a1dca1e9f54043a0918d60bd /net/packet
parent68ac31918ec359a2bfb9f897bb62c2940652d2b8 (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.c62
1 files changed, 31 insertions, 31 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index aec50a1e9849..aa4c73afa19a 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 }
628out:
629 mutex_unlock(&fanout_mutex); 629 mutex_unlock(&fanout_mutex);
630 return err; 630 return err;
631} 631}