[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <m1vds9k7vq.fsf_-_@fess.ebiederm.org>
Date: Tue, 20 Jan 2009 13:03:21 -0800
From: ebiederm@...ssion.com (Eric W. Biederman)
To: David Miller <davem@...emloft.net>
Cc: <netdev@...r.kernel.org>, Max Krasnyansky <maxk@...lcomm.com>,
Pavel Emelyanov <xemul@...nvz.org>
Subject: [PATCH 07/10] tun: Move read_wait into tun_file
The poll interface requires that the waitqueue exist while the struct
file is open. In the rare case when a tun device disappears before
the tun file closes we fail to provide this property, so move
read_wait.
This is safe now that tun_net_xmit is atomic with tun_detach.
Signed-off-by: Eric W. Biederman <ebiederm@...stanetworks.com>
---
drivers/net/tun.c | 18 ++++++++++--------
1 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index fa93160..030d985 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -90,6 +90,7 @@ struct tap_filter {
struct tun_file {
struct tun_struct *tun;
struct net *net;
+ wait_queue_head_t read_wait;
};
struct tun_struct {
@@ -98,7 +99,6 @@ struct tun_struct {
uid_t owner;
gid_t group;
- wait_queue_head_t read_wait;
struct sk_buff_head readq;
struct net_device *dev;
@@ -335,7 +335,7 @@ static int tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
/* Notify and wake up reader process */
if (tun->flags & TUN_FASYNC)
kill_fasync(&tun->fasync, SIGIO, POLL_IN);
- wake_up_interruptible(&tun->read_wait);
+ wake_up_interruptible(&tun->tfile->read_wait);
return 0;
drop:
@@ -420,7 +420,8 @@ static void tun_net_init(struct net_device *dev)
/* Poll */
static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
{
- struct tun_struct *tun = tun_get(file);
+ struct tun_file *tfile = file->private_data;
+ struct tun_struct *tun = __tun_get(tfile);
unsigned int mask = POLLOUT | POLLWRNORM;
if (!tun)
@@ -428,7 +429,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
- poll_wait(file, &tun->read_wait, wait);
+ poll_wait(file, &tfile->read_wait, wait);
if (!skb_queue_empty(&tun->readq))
mask |= POLLIN | POLLRDNORM;
@@ -702,7 +703,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
unsigned long count, loff_t pos)
{
struct file *file = iocb->ki_filp;
- struct tun_struct *tun = tun_get(file);
+ struct tun_file *tfile = file->private_data;
+ struct tun_struct *tun = __tun_get(tfile);
DECLARE_WAITQUEUE(wait, current);
struct sk_buff *skb;
ssize_t len, ret = 0;
@@ -718,7 +720,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
goto out;
}
- add_wait_queue(&tun->read_wait, &wait);
+ add_wait_queue(&tfile->read_wait, &wait);
while (len) {
current->state = TASK_INTERRUPTIBLE;
@@ -745,7 +747,7 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
}
current->state = TASK_RUNNING;
- remove_wait_queue(&tun->read_wait, &wait);
+ remove_wait_queue(&tfile->read_wait, &wait);
out:
tun_put(tun);
@@ -757,7 +759,6 @@ static void tun_setup(struct net_device *dev)
struct tun_struct *tun = netdev_priv(dev);
skb_queue_head_init(&tun->readq);
- init_waitqueue_head(&tun->read_wait);
tun->owner = -1;
tun->group = -1;
@@ -1136,6 +1137,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
return -ENOMEM;
tfile->tun = NULL;
tfile->net = get_net(current->nsproxy->net_ns);
+ init_waitqueue_head(&tfile->read_wait);
file->private_data = tfile;
return 0;
}
--
1.5.6.3
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists