* RCU usage:
* The macvtap_queue and the macvlan_dev are loosely coupled, the
* pointers from one to the other can only be read while rcu_read_lock
- * or macvtap_lock is held.
+ * or rtnl is held.
*
* Both the file and the macvlan_dev hold a reference on the macvtap_queue
* through sock_hold(&q->sk). When the macvlan_dev goes away first,
* file or the dev. The data structure is freed through __sk_free
* when both our references and any pending SKBs are gone.
*/
-static DEFINE_SPINLOCK(macvtap_lock);
static int macvtap_enable_queue(struct net_device *dev, struct file *file,
struct macvtap_queue *q)
struct macvlan_dev *vlan = netdev_priv(dev);
int err = -EINVAL;
- spin_lock(&macvtap_lock);
+ ASSERT_RTNL();
if (q->enabled)
goto out;
vlan->numvtaps++;
out:
- spin_unlock(&macvtap_lock);
return err;
}
struct macvlan_dev *vlan = netdev_priv(dev);
int err = -EBUSY;
- spin_lock(&macvtap_lock);
+ rtnl_lock();
if (vlan->numqueues == MAX_MACVTAP_QUEUES)
goto out;
vlan->numqueues++;
out:
- spin_unlock(&macvtap_lock);
+ rtnl_unlock();
return err;
}
-static int __macvtap_disable_queue(struct macvtap_queue *q)
+static int macvtap_disable_queue(struct macvtap_queue *q)
{
struct macvlan_dev *vlan;
struct macvtap_queue *nq;
- vlan = rcu_dereference_protected(q->vlan,
- lockdep_is_held(&macvtap_lock));
-
+ ASSERT_RTNL();
if (!q->enabled)
return -EINVAL;
+ vlan = rtnl_dereference(q->vlan);
+
if (vlan) {
int index = q->queue_index;
BUG_ON(index >= vlan->numvtaps);
- nq = rcu_dereference_protected(vlan->taps[vlan->numvtaps - 1],
- lockdep_is_held(&macvtap_lock));
+ nq = rtnl_dereference(vlan->taps[vlan->numvtaps - 1]);
nq->queue_index = index;
rcu_assign_pointer(vlan->taps[index], nq);
return 0;
}
-static int macvtap_disable_queue(struct macvtap_queue *q)
-{
- int err;
-
- spin_lock(&macvtap_lock);
- err = __macvtap_disable_queue(q);
- spin_unlock(&macvtap_lock);
-
- return err;
-}
-
/*
* The file owning the queue got closed, give up both
* the reference that the files holds as well as the
{
struct macvlan_dev *vlan;
- spin_lock(&macvtap_lock);
- vlan = rcu_dereference_protected(q->vlan,
- lockdep_is_held(&macvtap_lock));
+ rtnl_lock();
+ vlan = rtnl_dereference(q->vlan);
+
if (vlan) {
if (q->enabled)
- BUG_ON(__macvtap_disable_queue(q));
+ BUG_ON(macvtap_disable_queue(q));
vlan->numqueues--;
RCU_INIT_POINTER(q->vlan, NULL);
list_del_init(&q->next);
}
- spin_unlock(&macvtap_lock);
+ rtnl_unlock();
synchronize_rcu();
sock_put(&q->sk);
struct macvtap_queue *q, *tmp, *qlist[MAX_MACVTAP_QUEUES];
int i, j = 0;
- spin_lock(&macvtap_lock);
+ ASSERT_RTNL();
list_for_each_entry_safe(q, tmp, &vlan->queue_list, next) {
list_del_init(&q->next);
qlist[j++] = q;
BUG_ON(vlan->numqueues);
/* guarantee that any future macvtap_set_queue will fail */
vlan->numvtaps = MAX_MACVTAP_QUEUES;
- spin_unlock(&macvtap_lock);
-
- synchronize_rcu();
for (--j; j >= 0; j--)
sock_put(&qlist[j]->sk);
{
struct macvlan_dev *vlan;
- rcu_read_lock_bh();
- vlan = rcu_dereference_bh(q->vlan);
+ ASSERT_RTNL();
+ vlan = rtnl_dereference(q->vlan);
if (vlan)
dev_hold(vlan->dev);
- rcu_read_unlock_bh();
return vlan;
}
return ret;
case TUNGETIFF:
+ rtnl_lock();
vlan = macvtap_get_vlan(q);
- if (!vlan)
+ if (!vlan) {
+ rtnl_unlock();
return -ENOLINK;
+ }
ret = 0;
if (copy_to_user(&ifr->ifr_name, vlan->dev->name, IFNAMSIZ) ||
put_user(q->flags, &ifr->ifr_flags))
ret = -EFAULT;
macvtap_put_vlan(vlan);
+ rtnl_unlock();
return ret;
case TUNSETQUEUE:
if (get_user(u, &ifr->ifr_flags))
return -EFAULT;
- return macvtap_ioctl_set_queue(file, u);
+ rtnl_lock();
+ ret = macvtap_ioctl_set_queue(file, u);
+ rtnl_unlock();
case TUNGETFEATURES:
if (put_user(IFF_TAP | IFF_NO_PI | IFF_VNET_HDR |