[PATCH NET-PREV 23/51] hdlc_fr: Use __register_netdevice

Kirill Tkhai posted 51 patches 9 months ago
[PATCH NET-PREV 23/51] hdlc_fr: Use __register_netdevice
Posted by Kirill Tkhai 9 months ago
The objective is to make dependent devices share
the same nd_lock.

Finaly, taking nd_lock should be moved to ioctl
caller, but now we can't do this at least because
netdevice notifiers are not converted.

Signed-off-by: Kirill Tkhai <tkhai@ya.ru>
---
 drivers/net/wan/hdlc_fr.c |   18 ++++++++++++------
 net/core/dev_ioctl.c      |    1 +
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 81e72bc1891f..93c61083de76 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -1106,7 +1106,9 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
 	dev->priv_flags |= IFF_NO_QUEUE;
 	dev->ml_priv = pvc;
 
-	if (register_netdevice(dev) != 0) {
+	attach_nd_lock(dev, rcu_dereference_protected(frad->nd_lock, true));
+	if (__register_netdevice(dev) != 0) {
+		detach_nd_lock(dev);
 		free_netdev(dev);
 		delete_unused_pvcs(hdlc);
 		return -EIO;
@@ -1187,8 +1189,9 @@ static int fr_ioctl(struct net_device *dev, struct if_settings *ifs)
 	const size_t size = sizeof(fr_proto);
 	fr_proto new_settings;
 	hdlc_device *hdlc = dev_to_hdlc(dev);
+	struct nd_lock *nd_lock;
 	fr_proto_pvc pvc;
-	int result;
+	int result, err;
 
 	switch (ifs->type) {
 	case IF_GET_PROTO:
@@ -1272,10 +1275,13 @@ static int fr_ioctl(struct net_device *dev, struct if_settings *ifs)
 			result = ARPHRD_DLCI;
 
 		if (ifs->type == IF_PROTO_FR_ADD_PVC ||
-		    ifs->type == IF_PROTO_FR_ADD_ETH_PVC)
-			return fr_add_pvc(dev, pvc.dlci, result);
-		else
-			return fr_del_pvc(hdlc, pvc.dlci, result);
+		    ifs->type == IF_PROTO_FR_ADD_ETH_PVC) {
+			lock_netdev(dev, &nd_lock);
+			err = fr_add_pvc(dev, pvc.dlci, result);
+			unlock_netdev(nd_lock);
+		} else {
+			err = fr_del_pvc(hdlc, pvc.dlci, result);
+		}
 	}
 
 	return -EINVAL;
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 8592c052c0f4..dc2a0f513bac 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -496,6 +496,7 @@ static int dev_siocwandev(struct net_device *dev, struct if_settings *ifs)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
 
+	/* This may take nd_lock. See fr_add_pvc() */
 	if (ops->ndo_siocwandev) {
 		if (netif_device_present(dev))
 			return ops->ndo_siocwandev(dev, ifs);