Skip to content

Commit f207c10

Browse files
shemmingerdavem330
authored andcommitted
hv_netvsc: use RCU to protect vf_netdev
The vf_netdev pointer in the netvsc device context can simply be protected by RCU because network device destruction is already RCU synchronized. Signed-off-by: Stephen Hemminger <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e8ff40d commit f207c10

File tree

2 files changed

+16
-15
lines changed

2 files changed

+16
-15
lines changed

drivers/net/hyperv/hyperv_net.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ struct net_device_context {
695695
bool start_remove;
696696

697697
/* State to manage the associated VF interface. */
698-
struct net_device *vf_netdev;
698+
struct net_device __rcu *vf_netdev;
699699
bool vf_inject;
700700
atomic_t vf_use_cnt;
701701
/* 1: allocated, serial number is valid. 0: not allocated */

drivers/net/hyperv/netvsc_drv.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -667,18 +667,21 @@ int netvsc_recv_callback(struct hv_device *device_obj,
667667
{
668668
struct net_device *net = hv_get_drvdata(device_obj);
669669
struct net_device_context *net_device_ctx = netdev_priv(net);
670+
struct net_device *vf_netdev;
670671
struct sk_buff *skb;
671-
struct sk_buff *vf_skb;
672672
struct netvsc_stats *rx_stats;
673673
u32 bytes_recvd = packet->total_data_buflen;
674674
int ret = 0;
675675

676676
if (!net || net->reg_state != NETREG_REGISTERED)
677677
return NVSP_STAT_FAIL;
678678

679-
if (READ_ONCE(net_device_ctx->vf_inject)) {
679+
vf_netdev = rcu_dereference(net_device_ctx->vf_netdev);
680+
if (vf_netdev) {
681+
struct sk_buff *vf_skb;
682+
680683
atomic_inc(&net_device_ctx->vf_use_cnt);
681-
if (!READ_ONCE(net_device_ctx->vf_inject)) {
684+
if (!net_device_ctx->vf_inject) {
682685
/*
683686
* We raced; just move on.
684687
*/
@@ -694,13 +697,12 @@ int netvsc_recv_callback(struct hv_device *device_obj,
694697
* the host). Deliver these via the VF interface
695698
* in the guest.
696699
*/
697-
vf_skb = netvsc_alloc_recv_skb(net_device_ctx->vf_netdev,
700+
vf_skb = netvsc_alloc_recv_skb(vf_netdev,
698701
packet, csum_info, *data,
699702
vlan_tci);
700703
if (vf_skb != NULL) {
701-
++net_device_ctx->vf_netdev->stats.rx_packets;
702-
net_device_ctx->vf_netdev->stats.rx_bytes +=
703-
bytes_recvd;
704+
++vf_netdev->stats.rx_packets;
705+
vf_netdev->stats.rx_bytes += bytes_recvd;
704706
netif_receive_skb(vf_skb);
705707
} else {
706708
++net->stats.rx_dropped;
@@ -1232,7 +1234,7 @@ static struct net_device *get_netvsc_bymac(const u8 *mac)
12321234
return NULL;
12331235
}
12341236

1235-
static struct net_device *get_netvsc_byref(const struct net_device *vf_netdev)
1237+
static struct net_device *get_netvsc_byref(struct net_device *vf_netdev)
12361238
{
12371239
struct net_device *dev;
12381240

@@ -1248,7 +1250,7 @@ static struct net_device *get_netvsc_byref(const struct net_device *vf_netdev)
12481250
if (net_device_ctx->nvdev == NULL)
12491251
continue; /* device is removed */
12501252

1251-
if (net_device_ctx->vf_netdev == vf_netdev)
1253+
if (rtnl_dereference(net_device_ctx->vf_netdev) == vf_netdev)
12521254
return dev; /* a match */
12531255
}
12541256

@@ -1275,7 +1277,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
12751277

12761278
net_device_ctx = netdev_priv(ndev);
12771279
netvsc_dev = net_device_ctx->nvdev;
1278-
if (!netvsc_dev || net_device_ctx->vf_netdev)
1280+
if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
12791281
return NOTIFY_DONE;
12801282

12811283
netdev_info(ndev, "VF registering: %s\n", vf_netdev->name);
@@ -1285,7 +1287,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
12851287
try_module_get(THIS_MODULE);
12861288

12871289
dev_hold(vf_netdev);
1288-
net_device_ctx->vf_netdev = vf_netdev;
1290+
rcu_assign_pointer(net_device_ctx->vf_netdev, vf_netdev);
12891291
return NOTIFY_OK;
12901292
}
12911293

@@ -1379,7 +1381,8 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
13791381

13801382
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
13811383
netvsc_inject_disable(net_device_ctx);
1382-
net_device_ctx->vf_netdev = NULL;
1384+
1385+
RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL);
13831386
dev_put(vf_netdev);
13841387
module_put(THIS_MODULE);
13851388
return NOTIFY_OK;
@@ -1433,8 +1436,6 @@ static int netvsc_probe(struct hv_device *dev,
14331436
INIT_LIST_HEAD(&net_device_ctx->reconfig_events);
14341437

14351438
atomic_set(&net_device_ctx->vf_use_cnt, 0);
1436-
net_device_ctx->vf_netdev = NULL;
1437-
net_device_ctx->vf_inject = false;
14381439

14391440
net->netdev_ops = &device_ops;
14401441

0 commit comments

Comments
 (0)