af_packet: lock imbalance
authorEric Dumazet <eric.dumazet@gmail.com>
Thu, 7 Jul 2011 13:41:29 +0000 (06:41 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 7 Jul 2011 13:41:29 +0000 (06:41 -0700)
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>
net/packet/af_packet.c

index aec50a1..aa4c73a 100644 (file)
@@ -589,43 +589,43 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
                        break;
                }
        }
+       err = -EINVAL;
        if (match && match->defrag != defrag)
-               return -EINVAL;
+               goto out;
        if (!match) {
+               err = -ENOMEM;
                match = kzalloc(sizeof(*match), GFP_KERNEL);
-               if (match) {
-                       write_pnet(&match->net, sock_net(sk));
-                       match->id = id;
-                       match->type = type;
-                       match->defrag = defrag;
-                       atomic_set(&match->rr_cur, 0);
-                       INIT_LIST_HEAD(&match->list);
-                       spin_lock_init(&match->lock);
-                       atomic_set(&match->sk_ref, 0);
-                       match->prot_hook.type = po->prot_hook.type;
-                       match->prot_hook.dev = po->prot_hook.dev;
-                       match->prot_hook.func = packet_rcv_fanout;
-                       match->prot_hook.af_packet_priv = match;
-                       dev_add_pack(&match->prot_hook);
-                       list_add(&match->list, &fanout_list);
-               }
+               if (!match)
+                       goto out;
+               write_pnet(&match->net, sock_net(sk));
+               match->id = id;
+               match->type = type;
+               match->defrag = defrag;
+               atomic_set(&match->rr_cur, 0);
+               INIT_LIST_HEAD(&match->list);
+               spin_lock_init(&match->lock);
+               atomic_set(&match->sk_ref, 0);
+               match->prot_hook.type = po->prot_hook.type;
+               match->prot_hook.dev = po->prot_hook.dev;
+               match->prot_hook.func = packet_rcv_fanout;
+               match->prot_hook.af_packet_priv = match;
+               dev_add_pack(&match->prot_hook);
+               list_add(&match->list, &fanout_list);
        }
-       err = -ENOMEM;
-       if (match) {
-               err = -EINVAL;
-               if (match->type == type &&
-                   match->prot_hook.type == po->prot_hook.type &&
-                   match->prot_hook.dev == po->prot_hook.dev) {
-                       err = -ENOSPC;
-                       if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
-                               __dev_remove_pack(&po->prot_hook);
-                               po->fanout = match;
-                               atomic_inc(&match->sk_ref);
-                               __fanout_link(sk, po);
-                               err = 0;
-                       }
+       err = -EINVAL;
+       if (match->type == type &&
+           match->prot_hook.type == po->prot_hook.type &&
+           match->prot_hook.dev == po->prot_hook.dev) {
+               err = -ENOSPC;
+               if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
+                       __dev_remove_pack(&po->prot_hook);
+                       po->fanout = match;
+                       atomic_inc(&match->sk_ref);
+                       __fanout_link(sk, po);
+                       err = 0;
                }
        }
+out:
        mutex_unlock(&fanout_mutex);
        return err;
 }