diff options
author | Dexuan Cui <decui@microsoft.com> | 2016-06-09 18:47:24 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-08-31 13:05:41 +0200 |
commit | 638fea33aee858cc665297a76f0039e95a28ce0c (patch) | |
tree | b7d64f0d5feea234364b488021b729c1ef3434c0 /include/linux/hyperv.h | |
parent | e0fa3e5e7df61eb2c339c9f0067c202c0cdeec2c (diff) | |
download | lwn-638fea33aee858cc665297a76f0039e95a28ce0c.tar.gz lwn-638fea33aee858cc665297a76f0039e95a28ce0c.zip |
Drivers: hv: vmbus: fix the race when querying & updating the percpu list
There is a rare race when we remove an entry from the global list
hv_context.percpu_list[cpu] in hv_process_channel_removal() ->
percpu_channel_deq() -> list_del(): at this time, if vmbus_on_event() ->
process_chn_event() -> pcpu_relid2channel() is trying to query the list,
we can get the kernel fault.
Similarly, we also have the issue in the code path: vmbus_process_offer() ->
percpu_channel_enq().
We can resolve the issue by disabling the tasklet when updating the list.
The patch also moves vmbus_release_relid() to a later place where
the channel has been removed from the per-cpu and the global lists.
Reported-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/linux/hyperv.h')
-rw-r--r-- | include/linux/hyperv.h | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index b10954a66939..50f493eedeb5 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1357,6 +1357,9 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *, struct icmsg_negotiate *, u8 *, int, int); +void hv_event_tasklet_disable(struct vmbus_channel *channel); +void hv_event_tasklet_enable(struct vmbus_channel *channel); + void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); /* |