Netdev List
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: kuba@kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org, edumazet@google.com,
	pabeni@redhat.com, andrew+netdev@lunn.ch, horms@kernel.org,
	haiyangz@microsoft.com, wei.liu@kernel.org, decui@microsoft.com,
	kameroncarr@linux.microsoft.com, ernis@linux.microsoft.com
Subject: Re: [PATCH net-next v2 4/5] hv_netvsc: move a new VF to netvsc's netns from a work item
Date: Wed, 11 Nov 2026 10:48:52 +0000	[thread overview]
Message-ID: <179439413220.2199510.12624366739640158561@kernel.org> (raw)
In-Reply-To: <20261109194843.1353592-5-kuba@kernel.org>

Thank you for your contribution! Sashiko AI review found 2 potential
issue(s) to consider.

Critical: 0 · High: 0 (1) · Medium: 1 · Low: 1

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [Medium] netvsc_resume() now always requeues vfns_work, and it does so
  from the vmbus noirq resume phase (vmbus_pm:…
- [Low] netvsc_register_vf() takes a tracked reference on a VF registered
  in another netns (netdev_hold(vf_netdev, &vfns_dev_tracker) and stores…

Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but netvsc_probe()
  can free the net_device while its embedded vfns_work is still queued.

--

hv_netvsc: move a new VF to netvsc's netns from a work item

The patch stops calling dev_change_net_namespace() directly from the VF's
NETDEV_REGISTER notifier, which deadlocks for ops-locked VFs. Instead it
takes a reference on the VF in vfns_dev and has vfns_work move it, or take
it over if netvsc reached the VF's netns first. Suspend now keeps vfns_dev,
and resume queues the work again.

> diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
> index 61109ff9927fb..d534e574bcf22 100644
> --- a/drivers/net/hyperv/netvsc_drv.c
> +++ b/drivers/net/hyperv/netvsc_drv.c

[ ... ]

> @@ -2340,19 +2346,17 @@ static int netvsc_register_vf(struct net_device *vf_netdev, int context)
>  
>  	/* if synthetic interface is a different namespace,
>  	 * then move the VF to that namespace; join will be
> -	 * done again in that context.
> +	 * done again in that context. The VF's lock is held
> +	 * for its registration, so leave the move to vfns_work.
>  	 */
>  	if (!net_eq(dev_net(ndev), dev_net(vf_netdev))) {
> -		ret = dev_change_net_namespace(vf_netdev,
> -					       dev_net(ndev), "eth%d");
> -		if (ret)
> -			netdev_err(vf_netdev,
> -				   "could not move to same namespace as %s: %d\n",
> -				   ndev->name, ret);
> -		else
> -			netdev_info(vf_netdev,
> -				    "VF moved to namespace with: %s\n",
> -				    ndev->name);
> +		if (net_device_ctx->vfns_dev != vf_netdev) {
> +			netvsc_vfns_dev_put(net_device_ctx);
> +			netdev_hold(vf_netdev, &net_device_ctx->vfns_dev_tracker,
> +				    GFP_KERNEL);
> +			net_device_ctx->vfns_dev = vf_netdev;
> +		}

[Severity: Low]
What drops this reference if the VF is unregistered while it is parked
in vfns_dev?

The NETDEV_UNREGISTER handler finds netvsc only through the master upper
device:

drivers/net/hyperv/netvsc_drv.c:netvsc_unregister_vf() {
    ...
	ndev = get_netvsc_byref(vf_netdev);
	if (!ndev)
		return NOTIFY_DONE;
    ...
}

A VF that is held only in vfns_dev has not joined netvsc, so this lookup
returns NULL. Only vfns_work, through netvsc_event_set_vf_ns() and
netvsc_vfns_dev_put(), or netvsc_remove() drops the reference.

Usually the work runs soon and drops it when it sees reg_state !=
NETREG_REGISTERED. But netvsc_suspend() cancels vfns_work and keeps
vfns_dev until netvsc_resume() queues the work again.

If the VF is unregistered in that window, will unregister_netdevice()
wait in netdev_wait_allrefs_any() until thaw_noirq/restore_noirq, with
"waiting for ethX to become free" messages? netvsc ignores the repeated
NETDEV_UNREGISTER that the wait loop sends.

The window looks narrow, since hv_pci and the VF driver have already
suspended by then. Should the unregister path still check vfns_dev and
drop the reference there?

> +		schedule_delayed_work(&net_device_ctx->vfns_work, 0);
>  		return NOTIFY_DONE;
>  	}

[ ... ]

> @@ -2703,6 +2707,7 @@ static void netvsc_remove(struct hv_device *dev)
>  
>  	rtnl_lock();
>  	cancel_delayed_work_sync(&ndev_ctx->vfns_work);
> +	netvsc_vfns_dev_put(ndev_ctx);
>  
>  	nvdev = rtnl_dereference(ndev_ctx->nvdev);
>  	if (nvdev)

[Severity: High]
This isn't a bug introduced by this patch, but netvsc_remove() cancels
vfns_work and the netvsc_probe() error path does not. Can netvsc_probe()
free the net_device while vfns_work is still queued?

register_netdevice(net) sends NETDEV_REGISTER for the netvsc device, and
netvsc_netdev_event() queues the work:

	if (event_dev->netdev_ops == &device_ops && event == NETDEV_REGISTER) {
		ndev_ctx = netdev_priv(event_dev);
		schedule_delayed_work(&ndev_ctx->vfns_work, 0);
		return NOTIFY_DONE;
	}

If a later NETDEV_REGISTER notifier rejects the device, register_netdevice()
calls unregister_netdevice_queue() and returns an error. For example,
mpls_dev_notify() returns an error when mpls_add_dev() fails with -ENOMEM.

netvsc_probe() then goes through register_failed -> rndis_failed -> ... ->
free_netdev(net), and it never calls
cancel_delayed_work_sync(&net_device_ctx->vfns_work).

Probe holds RTNL at this point, so rtnl_trylock() fails in
netvsc_vfns_work() and the work requeues itself with a 1 jiffy delay.

If the work is still pending when free_netdev() frees the netdev_priv
memory, wouldn't the timer and workqueue linkage, and the container_of()
in netvsc_vfns_work(), touch freed memory?

[ ... ]

> @@ -2789,6 +2798,9 @@ static int netvsc_resume(struct hv_device *dev)
>  	netvsc_devinfo_put(device_info);
>  	net_device_ctx->saved_netvsc_dev_info = NULL;
>  
> +	/* pick up whatever netvsc_suspend() stopped vfns_work from doing */
> +	schedule_delayed_work(&net_device_ctx->vfns_work, 0);
> +

[Severity: Medium]
Can this run the VF move or takeover before the VF's own driver has
resumed?

netvsc_resume() is called from the vmbus noirq phase:

drivers/hv/vmbus_drv.c:vmbus_pm {
	.freeze_noirq	= vmbus_suspend,
	.thaw_noirq	= vmbus_resume,
	.poweroff_noirq	= vmbus_suspend,
	.restore_noirq	= vmbus_resume,
}

vfns_work runs on system_percpu_wq, which isn't freezable, and it only
needs rtnl_trylock(). It can therefore run before the VF's PCI driver gets
its normal-phase .thaw/.restore callback. This happens when vfns_dev, or a
netvsc netns move, is still pending when netvsc_suspend() cancels the
work.

netvsc_event_set_vf_ns() then calls one of two paths:

- dev_change_net_namespace(), which closes the VF via ndo_stop
- netif_close() followed by netvsc_register_vf()

The second path calls ndo_bpf, ndo_set_features and netvsc_vf_join(), and
netvsc_vf_join() schedules vf_takeover and dev_open().

Take mana as an example. mana_gd_suspend() -> mana_remove(..., true) ->
mana_detach() saves port_st_save and clears port_is_up. The early
netif_close() then hits:

drivers/net/ethernet/microsoft/mana/mana_en.c:mana_close() {
    ...
	if (!apc->port_is_up)
		return 0;
    ...
}

The core then clears IFF_UP. On resume, mana_attach() brings the port
back up from port_st_save. The hardware port is then up while the netdev
is marked down.

A later dev_open() from vf_takeover would then either fail with -ENODEV
while the device is still detached, or call mana_open() ->
mana_alloc_queues() a second time on a port that is already up.

Before this patch, netvsc_resume() didn't touch the VF. Should this
requeue wait until the VF driver has resumed?

>  	rtnl_unlock();
>  
>  	return ret;

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261109194843.1353592-1-kuba%40kernel.org

  reply	other threads:[~2026-11-11 10:48 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 19:48 [PATCH net-next v2 0/5] hv_netvsc: make XDP propagation act more like bonding Jakub Kicinski
2026-11-09 19:48 ` [PATCH net-next v2 1/5] hv_netvsc: fix the program refcount when the VF refuses XDP Jakub Kicinski
2026-11-09 19:48 ` [PATCH net-next v2 2/5] hv_netvsc: hold the VF's instance lock when installing XDP on it Jakub Kicinski
2026-11-11 10:48   ` netdev-bot+sashiko
2026-11-09 19:48 ` [PATCH net-next v2 3/5] hv_netvsc: treat the VF's XDP program the way bonding treats a slave's Jakub Kicinski
2026-11-11 10:48   ` netdev-bot+sashiko
2026-11-11 18:35     ` Jakub Kicinski
2026-11-09 19:48 ` [PATCH net-next v2 4/5] hv_netvsc: move a new VF to netvsc's netns from a work item Jakub Kicinski
2026-11-11 10:48   ` netdev-bot+sashiko [this message]
2026-11-11 18:40     ` Jakub Kicinski
2026-11-12 12:03       ` Paolo Abeni
2026-11-09 19:48 ` [PATCH net-next v2 5/5] hv_netvsc: let the core take XDP off a netvsc device that is going away Jakub Kicinski
2026-11-11 10:48   ` netdev-bot+sashiko
2026-11-11 18:45     ` Jakub Kicinski
2026-11-12 12:10 ` [PATCH net-next v2 0/5] hv_netvsc: make XDP propagation act more like bonding patchwork-bot+netdevbpf

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=179439413220.2199510.12624366739640158561@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=decui@microsoft.com \
    --cc=edumazet@google.com \
    --cc=ernis@linux.microsoft.com \
    --cc=haiyangz@microsoft.com \
    --cc=horms@kernel.org \
    --cc=kameroncarr@linux.microsoft.com \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=wei.liu@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