diff options
author | Ingo Molnar <mingo@kernel.org> | 2017-04-11 09:05:36 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-04-11 09:05:36 +0200 |
commit | 36a4dfc37856cae40e4d864950f768d8b7d4f9f5 (patch) | |
tree | 3aa6a1459a699b986632f64b740e8e98e3ce6500 /drivers/hv/channel.c | |
parent | a481db34b9beb7a9647c23f2320dd38a2b1d681f (diff) | |
parent | 39da7c509acff13fc8cb12ec1bb20337c988ed36 (diff) | |
download | linux-36a4dfc37856cae40e4d864950f768d8b7d4f9f5.tar.bz2 |
Merge tag 'v4.11-rc6' into sched/core, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/hv/channel.c')
-rw-r--r-- | drivers/hv/channel.c | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index bd0d1988feb2..321b8833fa6f 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -502,12 +502,15 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) wait_for_completion(&info->waitevent); - if (channel->rescind) { - ret = -ENODEV; - goto post_msg_err; - } - post_msg_err: + /* + * If the channel has been rescinded; + * we will be awakened by the rescind + * handler; set the error code to zero so we don't leak memory. + */ + if (channel->rescind) + ret = 0; + spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&info->msglistentry); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); @@ -530,15 +533,13 @@ static int vmbus_close_internal(struct vmbus_channel *channel) int ret; /* - * vmbus_on_event(), running in the tasklet, can race + * vmbus_on_event(), running in the per-channel tasklet, can race * with vmbus_close_internal() in the case of SMP guest, e.g., when * the former is accessing channel->inbound.ring_buffer, the latter - * could be freeing the ring_buffer pages. - * - * To resolve the race, we can serialize them by disabling the - * tasklet when the latter is running here. + * could be freeing the ring_buffer pages, so here we must stop it + * first. */ - hv_event_tasklet_disable(channel); + tasklet_disable(&channel->callback_event); /* * In case a device driver's probe() fails (e.g., @@ -605,8 +606,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); out: - hv_event_tasklet_enable(channel); - return ret; } |