Bluetooth: Add debug logs to help track locking issues
[cascardo/linux.git] / net / bluetooth / l2cap_sock.c
index f1a5156..b0efb72 100644 (file)
@@ -307,7 +307,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
        long timeo;
        int err = 0;
 
-       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+       lock_sock_nested(sk, L2CAP_NESTING_PARENT);
 
        timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
@@ -339,7 +339,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock,
 
                release_sock(sk);
                timeo = schedule_timeout(timeo);
-               lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+               lock_sock_nested(sk, L2CAP_NESTING_PARENT);
        }
        __set_current_state(TASK_RUNNING);
        remove_wait_queue(sk_sleep(sk), &wait);
@@ -1102,6 +1102,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
        chan = l2cap_pi(sk)->chan;
        conn = chan->conn;
 
+       BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
+
        if (conn)
                mutex_lock(&conn->chan_lock);
 
@@ -1159,12 +1161,16 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
 {
        struct sock *sk;
 
-       BT_DBG("parent %p", parent);
+       BT_DBG("parent %p state %s", parent,
+              state_to_string(parent->sk_state));
 
        /* Close not yet accepted channels */
        while ((sk = bt_accept_dequeue(parent, NULL))) {
                struct l2cap_chan *chan = l2cap_pi(sk)->chan;
 
+               BT_DBG("child chan %p state %s", chan,
+                      state_to_string(chan->state));
+
                l2cap_chan_lock(chan);
                __clear_chan_timer(chan);
                l2cap_chan_close(chan, ECONNRESET);
@@ -1252,7 +1258,16 @@ static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err)
        struct sock *sk = chan->data;
        struct sock *parent;
 
-       lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+       BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
+
+       /* This callback can be called both for server (BT_LISTEN)
+        * sockets as well as "normal" ones. To avoid lockdep warnings
+        * with child socket locking (through l2cap_sock_cleanup_listen)
+        * we need separation into separate nesting levels. The simplest
+        * way to accomplish this is to inherit the nesting level used
+        * for the channel.
+        */
+       lock_sock_nested(sk, atomic_read(&chan->nesting));
 
        parent = bt_sk(sk)->parent;
 
@@ -1503,9 +1518,6 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
                l2cap_chan_set_defaults(chan);
        }
 
-       /* Set default lock nesting level */
-       atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
-
        /* Default config options */
        chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;