diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-27 09:13:04 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-03-27 09:13:04 +0200 |
commit | 57c0eabbd57e1a0872122525f6eeefe1f6529c33 (patch) | |
tree | 788d036bfbc9c92fb7663588033f50d2d6f5c828 /drivers/hv/channel.c | |
parent | drivers, firewire: convert fw_node.ref_count from atomic_t to refcount_t (diff) | |
parent | Linux 4.11-rc4 (diff) | |
download | linux-57c0eabbd57e1a0872122525f6eeefe1f6529c33.tar.xz linux-57c0eabbd57e1a0872122525f6eeefe1f6529c33.zip |
Merge 4.11-rc4 into char-misc-next
We want the char-misc fixes in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.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 5c1aa1c09064..736ac76d2a6a 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; } |