aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/macvtap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/macvtap.c')
-rw-r--r--drivers/net/macvtap.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 5933621ac3ff..2300e4599520 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -39,7 +39,7 @@ struct macvtap_queue {
39 struct socket sock; 39 struct socket sock;
40 struct socket_wq wq; 40 struct socket_wq wq;
41 int vnet_hdr_sz; 41 int vnet_hdr_sz;
42 struct macvlan_dev *vlan; 42 struct macvlan_dev __rcu *vlan;
43 struct file *file; 43 struct file *file;
44 unsigned int flags; 44 unsigned int flags;
45}; 45};
@@ -141,7 +141,8 @@ static void macvtap_put_queue(struct macvtap_queue *q)
141 struct macvlan_dev *vlan; 141 struct macvlan_dev *vlan;
142 142
143 spin_lock(&macvtap_lock); 143 spin_lock(&macvtap_lock);
144 vlan = rcu_dereference(q->vlan); 144 vlan = rcu_dereference_protected(q->vlan,
145 lockdep_is_held(&macvtap_lock));
145 if (vlan) { 146 if (vlan) {
146 int index = get_slot(vlan, q); 147 int index = get_slot(vlan, q);
147 148
@@ -219,7 +220,8 @@ static void macvtap_del_queues(struct net_device *dev)
219 /* macvtap_put_queue can free some slots, so go through all slots */ 220 /* macvtap_put_queue can free some slots, so go through all slots */
220 spin_lock(&macvtap_lock); 221 spin_lock(&macvtap_lock);
221 for (i = 0; i < MAX_MACVTAP_QUEUES && vlan->numvtaps; i++) { 222 for (i = 0; i < MAX_MACVTAP_QUEUES && vlan->numvtaps; i++) {
222 q = rcu_dereference(vlan->taps[i]); 223 q = rcu_dereference_protected(vlan->taps[i],
224 lockdep_is_held(&macvtap_lock));
223 if (q) { 225 if (q) {
224 qlist[j++] = q; 226 qlist[j++] = q;
225 rcu_assign_pointer(vlan->taps[i], NULL); 227 rcu_assign_pointer(vlan->taps[i], NULL);
@@ -569,7 +571,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
569 } 571 }
570 572
571 rcu_read_lock_bh(); 573 rcu_read_lock_bh();
572 vlan = rcu_dereference(q->vlan); 574 vlan = rcu_dereference_bh(q->vlan);
573 if (vlan) 575 if (vlan)
574 macvlan_start_xmit(skb, vlan->dev); 576 macvlan_start_xmit(skb, vlan->dev);
575 else 577 else
@@ -583,7 +585,7 @@ err_kfree:
583 585
584err: 586err:
585 rcu_read_lock_bh(); 587 rcu_read_lock_bh();
586 vlan = rcu_dereference(q->vlan); 588 vlan = rcu_dereference_bh(q->vlan);
587 if (vlan) 589 if (vlan)
588 vlan->dev->stats.tx_dropped++; 590 vlan->dev->stats.tx_dropped++;
589 rcu_read_unlock_bh(); 591 rcu_read_unlock_bh();
@@ -631,7 +633,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
631 ret = skb_copy_datagram_const_iovec(skb, 0, iv, vnet_hdr_len, len); 633 ret = skb_copy_datagram_const_iovec(skb, 0, iv, vnet_hdr_len, len);
632 634
633 rcu_read_lock_bh(); 635 rcu_read_lock_bh();
634 vlan = rcu_dereference(q->vlan); 636 vlan = rcu_dereference_bh(q->vlan);
635 if (vlan) 637 if (vlan)
636 macvlan_count_rx(vlan, len, ret == 0, 0); 638 macvlan_count_rx(vlan, len, ret == 0, 0);
637 rcu_read_unlock_bh(); 639 rcu_read_unlock_bh();
@@ -727,7 +729,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
727 729
728 case TUNGETIFF: 730 case TUNGETIFF:
729 rcu_read_lock_bh(); 731 rcu_read_lock_bh();
730 vlan = rcu_dereference(q->vlan); 732 vlan = rcu_dereference_bh(q->vlan);
731 if (vlan) 733 if (vlan)
732 dev_hold(vlan->dev); 734 dev_hold(vlan->dev);
733 rcu_read_unlock_bh(); 735 rcu_read_unlock_bh();
@@ -736,7 +738,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
736 return -ENOLINK; 738 return -ENOLINK;
737 739
738 ret = 0; 740 ret = 0;
739 if (copy_to_user(&ifr->ifr_name, q->vlan->dev->name, IFNAMSIZ) || 741 if (copy_to_user(&ifr->ifr_name, vlan->dev->name, IFNAMSIZ) ||
740 put_user(q->flags, &ifr->ifr_flags)) 742 put_user(q->flags, &ifr->ifr_flags))
741 ret = -EFAULT; 743 ret = -EFAULT;
742 dev_put(vlan->dev); 744 dev_put(vlan->dev);