|
|
@@ -641,7 +641,7 @@ struct sock *__vsock_create(struct net *net,
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(__vsock_create);
|
|
|
|
|
|
-static void __vsock_release(struct sock *sk)
|
|
|
+static void __vsock_release(struct sock *sk, int level)
|
|
|
{
|
|
|
if (sk) {
|
|
|
struct sk_buff *skb;
|
|
|
@@ -651,9 +651,17 @@ static void __vsock_release(struct sock *sk)
|
|
|
vsk = vsock_sk(sk);
|
|
|
pending = NULL; /* Compiler warning. */
|
|
|
|
|
|
+ /* The release call is supposed to use lock_sock_nested()
|
|
|
+ * rather than lock_sock(), if a sock lock should be acquired.
|
|
|
+ */
|
|
|
transport->release(vsk);
|
|
|
|
|
|
- lock_sock(sk);
|
|
|
+ /* When "level" is SINGLE_DEPTH_NESTING, use the nested
|
|
|
+ * version to avoid the warning "possible recursive locking
|
|
|
+ * detected". When "level" is 0, lock_sock_nested(sk, level)
|
|
|
+ * is the same as lock_sock(sk).
|
|
|
+ */
|
|
|
+ lock_sock_nested(sk, level);
|
|
|
sock_orphan(sk);
|
|
|
sk->sk_shutdown = SHUTDOWN_MASK;
|
|
|
|
|
|
@@ -662,7 +670,7 @@ static void __vsock_release(struct sock *sk)
|
|
|
|
|
|
/* Clean up any sockets that never were accepted. */
|
|
|
while ((pending = vsock_dequeue_accept(sk)) != NULL) {
|
|
|
- __vsock_release(pending);
|
|
|
+ __vsock_release(pending, SINGLE_DEPTH_NESTING);
|
|
|
sock_put(pending);
|
|
|
}
|
|
|
|
|
|
@@ -711,7 +719,7 @@ EXPORT_SYMBOL_GPL(vsock_stream_has_space);
|
|
|
|
|
|
static int vsock_release(struct socket *sock)
|
|
|
{
|
|
|
- __vsock_release(sock->sk);
|
|
|
+ __vsock_release(sock->sk, 0);
|
|
|
sock->sk = NULL;
|
|
|
sock->state = SS_FREE;
|
|
|
|