Skip to content

Commit

Permalink
Merge branch 'hv_netvsc-races'
Browse files Browse the repository at this point in the history
Vitaly Kuznetsov says:

====================
hv_netvsc: avoid races on mtu change/set channels

Changes since v1:
- Rebased to net-next [Haiyang Zhang]

Original description:

MTU change and set channels operations are implemented as netvsc device
re-creation destroying internal structures (struct net_device stays). This
is really unfortunate but there is no support from Hyper-V host to do it
in a different way. Such re-creation is unsurprisingly racy, Haiyang
reported a crash when netvsc_change_mtu() is racing with
netvsc_link_change() but I was able to identify additional races upon
investigation. Both netvsc_set_channels() and netvsc_change_mtu() race
against:
1) netvsc_link_change()
2) netvsc_remove()
3) netvsc_send()

To solve these issues without introducing new locks some refactoring is
required. We need to get rid of very complex link graph in all the
internal structures and avoid traveling through structures which are being
removed.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 16, 2016
2 parents da47b45 + 8809883 commit 860d7ef
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 198 deletions.
17 changes: 7 additions & 10 deletions drivers/net/hyperv/hyperv_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ enum rndis_device_state {
};

struct rndis_device {
struct netvsc_device *net_dev;
struct net_device *ndev;

enum rndis_device_state state;
bool link_state;
Expand Down Expand Up @@ -202,7 +202,7 @@ int rndis_filter_receive(struct hv_device *dev,
int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);

void netvsc_switch_datapath(struct netvsc_device *nv_dev, bool vf);
void netvsc_switch_datapath(struct net_device *nv_dev, bool vf);

#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF)

Expand Down Expand Up @@ -653,6 +653,8 @@ struct garp_wrk {
struct net_device_context {
/* point back to our device context */
struct hv_device *device_ctx;
/* netvsc_device */
struct netvsc_device *nvdev;
/* reconfigure work */
struct delayed_work dwork;
/* last reconfig time */
Expand All @@ -672,17 +674,17 @@ struct net_device_context {
/* Ethtool settings */
u8 duplex;
u32 speed;

/* the device is going away */
bool start_remove;
};

/* Per netvsc device */
struct netvsc_device {
struct hv_device *dev;

u32 nvsp_version;

atomic_t num_outstanding_sends;
wait_queue_head_t wait_drain;
bool start_remove;
bool destroy;

/* Receive buffer allocated by us but manages by NetVSP */
Expand All @@ -708,8 +710,6 @@ struct netvsc_device {
struct nvsp_message revoke_packet;
/* unsigned char HwMacAddr[HW_MACADDR_LEN]; */

struct net_device *ndev;

struct vmbus_channel *chn_table[VRSS_CHANNEL_MAX];
u32 send_table[VRSS_SEND_TAB_SIZE];
u32 max_chn;
Expand All @@ -732,9 +732,6 @@ struct netvsc_device {
u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
u32 pkt_align; /* alignment bytes, e.g. 8 */

/* The net device context */
struct net_device_context *nd_ctx;

/* 1: allocated, serial number is valid. 0: not allocated */
u32 vf_alloc;
/* Serial number of the VF to team with */
Expand Down
Loading

0 comments on commit 860d7ef

Please sign in to comment.