aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-03-18 23:29:41 -0400
committerDavid S. Miller <davem@davemloft.net>2012-03-18 23:29:41 -0400
commit4da0bd736552e6377b407b3c3d3ae518ebbdd269 (patch)
treef0da9f843b8033565c3ca4103fccb17a60688326 /drivers/net/tun.c
parent81a430ac1b88b0702c57d2513e247317e810e04d (diff)
parentc16fa4f2ad19908a47c63d8fa436a1178438c7e7 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 2c5d34957c5..74d7f76d14a 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -359,7 +359,7 @@ static void tun_free_netdev(struct net_device *dev)
{
struct tun_struct *tun = netdev_priv(dev);
- sock_put(tun->socket.sk);
+ sk_release_kernel(tun->socket.sk);
}
/* Net device open. */
@@ -980,10 +980,18 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
return ret;
}
+static int tun_release(struct socket *sock)
+{
+ if (sock->sk)
+ sock_put(sock->sk);
+ return 0;
+}
+
/* Ops structure to mimic raw sockets with tun */
static const struct proto_ops tun_socket_ops = {
.sendmsg = tun_sendmsg,
.recvmsg = tun_recvmsg,
+ .release = tun_release,
};
static struct proto tun_proto = {
@@ -1110,10 +1118,11 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
err = -ENOMEM;
- sk = sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &tun_proto);
+ sk = sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, &tun_proto);
if (!sk)
goto err_free_dev;
+ sk_change_net(sk, net);
tun->socket.wq = &tun->wq;
init_waitqueue_head(&tun->wq.wait);
tun->socket.ops = &tun_socket_ops;
@@ -1174,7 +1183,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
return 0;
err_free_sk:
- sock_put(sk);
+ tun_free_netdev(dev);
err_free_dev:
free_netdev(dev);
failed: