diff options
Diffstat (limited to 'drivers/net/macvtap.c')
-rw-r--r-- | drivers/net/macvtap.c | 18 |
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 | ||
584 | err: | 586 | err: |
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); |