netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Vlad Yasevich <vyasevic@redhat.com>
To: netdev@vger.kernel.org
Cc: mst@redhat.com, eric.dumazet@gmail.com, davem@davemloft.net,
	Vlad Yasevich <vyasevic@redhat.com>
Subject: [PATCHv2 net-next 1/4] macvtap: Convert to using rtnl lock
Date: Tue, 25 Jun 2013 16:04:19 -0400	[thread overview]
Message-ID: <1372190662-30815-2-git-send-email-vyasevic@redhat.com> (raw)
In-Reply-To: <1372190662-30815-1-git-send-email-vyasevic@redhat.com>

Macvtap uses a private lock to protect the relationship between
macvtap_queue and macvlan_dev.  The private lock is not needed
since the relationship is managed by user via open(), release(),
and dellink() calls.  dellink() already happens under rtnl, so
we can safely convert open() and release(), and use it in ioctl()
as well.

Suggested by Eric Dumazet.

Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
 drivers/net/macvtap.c | 62 +++++++++++++++++++++------------------------------
 1 file changed, 25 insertions(+), 37 deletions(-)

diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 5a76f20..efbf2eb 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -69,7 +69,7 @@ static const struct proto_ops macvtap_socket_ops;
  * 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,
@@ -81,7 +81,6 @@ static const struct proto_ops macvtap_socket_ops;
  * 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)
@@ -89,7 +88,7 @@ static int macvtap_enable_queue(struct net_device *dev, struct file *file,
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	int err = -EINVAL;
 
-	spin_lock(&macvtap_lock);
+	ASSERT_RTNL();
 
 	if (q->enabled)
 		goto out;
@@ -101,7 +100,6 @@ static int macvtap_enable_queue(struct net_device *dev, struct file *file,
 
 	vlan->numvtaps++;
 out:
-	spin_unlock(&macvtap_lock);
 	return err;
 }
 
@@ -111,7 +109,7 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file,
 	struct macvlan_dev *vlan = netdev_priv(dev);
 	int err = -EBUSY;
 
-	spin_lock(&macvtap_lock);
+	rtnl_lock();
 	if (vlan->numqueues == MAX_MACVTAP_QUEUES)
 		goto out;
 
@@ -130,26 +128,25 @@ static int macvtap_set_queue(struct net_device *dev, struct file *file,
 	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);
@@ -162,17 +159,6 @@ static int __macvtap_disable_queue(struct macvtap_queue *q)
 	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
@@ -185,12 +171,12 @@ static void macvtap_put_queue(struct macvtap_queue *q)
 {
 	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);
@@ -198,7 +184,7 @@ static void macvtap_put_queue(struct macvtap_queue *q)
 		list_del_init(&q->next);
 	}
 
-	spin_unlock(&macvtap_lock);
+	rtnl_unlock();
 
 	synchronize_rcu();
 	sock_put(&q->sk);
@@ -260,7 +246,7 @@ static void macvtap_del_queues(struct net_device *dev)
 	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;
@@ -275,9 +261,6 @@ static void macvtap_del_queues(struct net_device *dev)
 	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);
@@ -941,11 +924,10 @@ static struct macvlan_dev *macvtap_get_vlan(struct macvtap_queue *q)
 {
 	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;
 }
@@ -1008,21 +990,27 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
 		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 |
-- 
1.8.1.4

  reply	other threads:[~2013-06-25 20:04 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-25 20:04 [PATCHv2 net-next 0/4] macvtap: locking and offload control Vlad Yasevich
2013-06-25 20:04 ` Vlad Yasevich [this message]
2013-06-25 20:31   ` [PATCHv2 net-next 1/4] macvtap: Convert to using rtnl lock Eric Dumazet
2013-06-25 20:04 ` [PATCHv2 net-next 2/4] macvtap: Consistently use rcu functions Vlad Yasevich
2013-06-25 20:31   ` Eric Dumazet
2013-06-25 20:04 ` [PATCHv2 net-next 3/4] macvtap: Let TUNSETOFFLOAD actually controll offload features Vlad Yasevich
2013-06-25 20:04 ` [PATCHv2 net-next 4/4] macvtap: Perform GSO on forwarding path Vlad Yasevich
2013-06-25 20:25   ` Sergei Shtylyov
2013-06-25 23:46     ` David Miller
2013-06-25 23:45 ` [PATCHv2 net-next 0/4] macvtap: locking and offload control David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1372190662-30815-2-git-send-email-vyasevic@redhat.com \
    --to=vyasevic@redhat.com \
    --cc=davem@davemloft.net \
    --cc=eric.dumazet@gmail.com \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).