Commit 6da7a0f9 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'dev-covnert-dev_change_name-to-per-netns-rtnl'

Kuniyuki Iwashima says:

====================
dev: Covnert dev_change_name() to per-netns RTNL.

Patch 1 adds a missing netdev_rename_lock in dev_change_name()
and Patch 2 removes unnecessary devnet_rename_sem there.

Patch 3 replaces RTNL with rtnl_net_lock() in dev_ifsioc(),
and now dev_change_name() is always called under per-netns RTNL.

Given it's close to -rc8 and Patch 1 touches the trivial unlikely
path, can Patch 1 go into net-next ?  Otherwise I'll post Patch 2 & 3
separately in the next cycle.
====================

Link: https://patch.msgid.link/20250115095545.52709-1-kuniyu@amazon.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 8d20dcda be94cfdb
Loading
Loading
Loading
Loading
+6 −19
Original line number Diff line number Diff line
@@ -181,8 +181,6 @@ static DEFINE_SPINLOCK(napi_hash_lock);
static unsigned int napi_gen_id = NR_CPUS;
static DEFINE_READ_MOSTLY_HASHTABLE(napi_hash, 8);

static DECLARE_RWSEM(devnet_rename_sem);

static inline void dev_base_seq_inc(struct net *net)
{
	unsigned int val = net->dev_base_seq + 1;
@@ -1350,23 +1348,16 @@ static int dev_get_valid_name(struct net *net, struct net_device *dev,
 */
int dev_change_name(struct net_device *dev, const char *newname)
{
	struct net *net = dev_net(dev);
	unsigned char old_assign_type;
	char oldname[IFNAMSIZ];
	int err = 0;
	int ret;
	struct net *net;

	ASSERT_RTNL();
	BUG_ON(!dev_net(dev));

	net = dev_net(dev);

	down_write(&devnet_rename_sem);
	ASSERT_RTNL_NET(net);

	if (strncmp(newname, dev->name, IFNAMSIZ) == 0) {
		up_write(&devnet_rename_sem);
	if (!strncmp(newname, dev->name, IFNAMSIZ))
		return 0;
	}

	memcpy(oldname, dev->name, IFNAMSIZ);

@@ -1374,10 +1365,8 @@ int dev_change_name(struct net_device *dev, const char *newname)
	err = dev_get_valid_name(net, dev, newname);
	write_sequnlock_bh(&netdev_rename_lock);

	if (err < 0) {
		up_write(&devnet_rename_sem);
	if (err < 0)
		return err;
	}

	if (oldname[0] && !strchr(oldname, '%'))
		netdev_info(dev, "renamed from %s%s\n", oldname,
@@ -1389,14 +1378,13 @@ int dev_change_name(struct net_device *dev, const char *newname)
rollback:
	ret = device_rename(&dev->dev, dev->name);
	if (ret) {
		write_seqlock_bh(&netdev_rename_lock);
		memcpy(dev->name, oldname, IFNAMSIZ);
		write_sequnlock_bh(&netdev_rename_lock);
		WRITE_ONCE(dev->name_assign_type, old_assign_type);
		up_write(&devnet_rename_sem);
		return ret;
	}

	up_write(&devnet_rename_sem);

	netdev_adjacent_rename_links(dev, oldname);

	netdev_name_node_del(dev->name_node);
@@ -1412,7 +1400,6 @@ int dev_change_name(struct net_device *dev, const char *newname)
		/* err >= 0 after dev_alloc_name() or stores the first errno */
		if (err >= 0) {
			err = ret;
			down_write(&devnet_rename_sem);
			write_seqlock_bh(&netdev_rename_lock);
			memcpy(dev->name, oldname, IFNAMSIZ);
			write_sequnlock_bh(&netdev_rename_lock);
+17 −9
Original line number Diff line number Diff line
@@ -543,7 +543,7 @@ static int dev_siocwandev(struct net_device *dev, struct if_settings *ifs)
}

/*
 *	Perform the SIOCxIFxxx calls, inside rtnl_lock()
 *	Perform the SIOCxIFxxx calls, inside rtnl_net_lock()
 */
static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,
		      unsigned int cmd)
@@ -620,11 +620,14 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,
			return -ENODEV;
		if (!netif_is_bridge_master(dev))
			return -EOPNOTSUPP;

		netdev_hold(dev, &dev_tracker, GFP_KERNEL);
		rtnl_unlock();
		rtnl_net_unlock(net);

		err = br_ioctl_call(net, netdev_priv(dev), cmd, ifr, NULL);

		netdev_put(dev, &dev_tracker);
		rtnl_lock();
		rtnl_net_lock(net);
		return err;

	case SIOCDEVPRIVATE ... SIOCDEVPRIVATE + 15:
@@ -770,9 +773,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
		dev_load(net, ifr->ifr_name);
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
			return -EPERM;
		rtnl_lock();

		rtnl_net_lock(net);
		ret = dev_ifsioc(net, ifr, data, cmd);
		rtnl_unlock();
		rtnl_net_unlock(net);

		if (colon)
			*colon = ':';
		return ret;
@@ -816,9 +821,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
	case SIOCBONDSLAVEINFOQUERY:
	case SIOCBONDINFOQUERY:
		dev_load(net, ifr->ifr_name);
		rtnl_lock();

		rtnl_net_lock(net);
		ret = dev_ifsioc(net, ifr, data, cmd);
		rtnl_unlock();
		rtnl_net_unlock(net);

		if (need_copyout)
			*need_copyout = false;
		return ret;
@@ -841,9 +848,10 @@ int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
		    (cmd >= SIOCDEVPRIVATE &&
		     cmd <= SIOCDEVPRIVATE + 15)) {
			dev_load(net, ifr->ifr_name);
			rtnl_lock();

			rtnl_net_lock(net);
			ret = dev_ifsioc(net, ifr, data, cmd);
			rtnl_unlock();
			rtnl_net_unlock(net);
			return ret;
		}
		return -ENOTTY;
+3 −12
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ static int rtnl_net_debug_event(struct notifier_block *nb,
	case NETDEV_CHANGEADDR:
	case NETDEV_PRE_CHANGEADDR:
	case NETDEV_GOING_DOWN:
	case NETDEV_CHANGENAME:
	case NETDEV_FEAT_CHANGE:
	case NETDEV_BONDING_FAILOVER:
	case NETDEV_PRE_UP:
@@ -60,18 +59,10 @@ static int rtnl_net_debug_event(struct notifier_block *nb,
		ASSERT_RTNL();
		break;

	/* Once an event fully supports RTNL_NET, move it here
	 * and remove "if (0)" below.
	 *
	 * case NETDEV_XXX:
	 *	ASSERT_RTNL_NET(net);
	 *	break;
	 */
	}

	/* Just to avoid unused-variable error for dev and net. */
	if (0)
	case NETDEV_CHANGENAME:
		ASSERT_RTNL_NET(net);
		break;
	}

	return NOTIFY_DONE;
}