diff options
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r-- | drivers/net/tun.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 7ab94c825b57..eba1271b9735 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/kernel.h> | 48 | #include <linux/kernel.h> |
49 | #include <linux/major.h> | 49 | #include <linux/major.h> |
50 | #include <linux/slab.h> | 50 | #include <linux/slab.h> |
51 | #include <linux/smp_lock.h> | ||
51 | #include <linux/poll.h> | 52 | #include <linux/poll.h> |
52 | #include <linux/fcntl.h> | 53 | #include <linux/fcntl.h> |
53 | #include <linux/init.h> | 54 | #include <linux/init.h> |
@@ -602,6 +603,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
602 | tun->attached = 1; | 603 | tun->attached = 1; |
603 | get_net(dev_net(tun->dev)); | 604 | get_net(dev_net(tun->dev)); |
604 | 605 | ||
606 | /* Make sure persistent devices do not get stuck in | ||
607 | * xoff state. | ||
608 | */ | ||
609 | if (netif_running(tun->dev)) | ||
610 | netif_wake_queue(tun->dev); | ||
611 | |||
605 | strcpy(ifr->ifr_name, tun->dev->name); | 612 | strcpy(ifr->ifr_name, tun->dev->name); |
606 | return 0; | 613 | return 0; |
607 | 614 | ||
@@ -796,22 +803,26 @@ static int tun_chr_fasync(int fd, struct file *file, int on) | |||
796 | 803 | ||
797 | DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on); | 804 | DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on); |
798 | 805 | ||
806 | lock_kernel(); | ||
799 | if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0) | 807 | if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0) |
800 | return ret; | 808 | goto out; |
801 | 809 | ||
802 | if (on) { | 810 | if (on) { |
803 | ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0); | 811 | ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0); |
804 | if (ret) | 812 | if (ret) |
805 | return ret; | 813 | goto out; |
806 | tun->flags |= TUN_FASYNC; | 814 | tun->flags |= TUN_FASYNC; |
807 | } else | 815 | } else |
808 | tun->flags &= ~TUN_FASYNC; | 816 | tun->flags &= ~TUN_FASYNC; |
809 | 817 | ret = 0; | |
810 | return 0; | 818 | out: |
819 | unlock_kernel(); | ||
820 | return ret; | ||
811 | } | 821 | } |
812 | 822 | ||
813 | static int tun_chr_open(struct inode *inode, struct file * file) | 823 | static int tun_chr_open(struct inode *inode, struct file * file) |
814 | { | 824 | { |
825 | cycle_kernel_lock(); | ||
815 | DBG1(KERN_INFO "tunX: tun_chr_open\n"); | 826 | DBG1(KERN_INFO "tunX: tun_chr_open\n"); |
816 | file->private_data = NULL; | 827 | file->private_data = NULL; |
817 | return 0; | 828 | return 0; |