Skip to content

Commit

Permalink
rh7: Drivers: hv: vmbus: Fix a rescind handling bug
Browse files Browse the repository at this point in the history
  • Loading branch information
nickme committed Jan 24, 2017
1 parent cd99922 commit 491dcca
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 0 deletions.
18 changes: 18 additions & 0 deletions hv-rhel7.x/hv/channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
}

init_completion(&open_info->waitevent);
open_info->waiting_channel = newchannel;

open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
Expand Down Expand Up @@ -195,6 +196,11 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
list_del(&open_info->msglistentry);
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);

if (newchannel->rescind) {
err = -ENODEV;
goto error_free_gpadl;
}

if (open_info->response.open_result.status) {
err = -EAGAIN;
goto error_free_gpadl;
Expand Down Expand Up @@ -406,6 +412,7 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
return ret;

init_completion(&msginfo->waitevent);
msginfo->waiting_channel = channel;

gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
Expand Down Expand Up @@ -442,6 +449,11 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
}
wait_for_completion(&msginfo->waitevent);

if (channel->rescind) {
ret = -ENODEV;
goto cleanup;
}

/* At this point, we received the gpadl created msg */
*gpadl_handle = gpadlmsg->gpadl;

Expand Down Expand Up @@ -475,6 +487,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
return -ENOMEM;

init_completion(&info->waitevent);
info->waiting_channel = channel;

msg = (struct vmbus_channel_gpadl_teardown *)info->msg;

Expand All @@ -494,6 +507,11 @@ 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:
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
list_del(&info->msglistentry);
Expand Down
25 changes: 25 additions & 0 deletions hv-rhel7.x/hv/channel_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,29 @@ static const struct {
{ HV_RDV_GUID },
};

/*
* The rescinded channel may be blocked waiting for a response from the host;
* take care of that.
*/
static void vmbus_rescind_cleanup(struct vmbus_channel *channel)
{
struct vmbus_channel_msginfo *msginfo;
unsigned long flags;


spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);

list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
msglistentry) {

if (msginfo->waiting_channel == channel) {
complete(&msginfo->waitevent);
break;
}
}
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
}

static bool is_unsupported_vmbus_devs(const uuid_le *guid)
{
int i;
Expand Down Expand Up @@ -807,6 +830,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
channel->rescind = true;
spin_unlock_irqrestore(&channel->lock, flags);

vmbus_rescind_cleanup(channel);

if (channel->device_obj) {
if (is_hvsock_channel(channel) &&
channel->hvsock_event_callback) {
Expand Down
1 change: 1 addition & 0 deletions hv-rhel7.x/hv/include/linux/hyperv.h
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,7 @@ struct vmbus_channel_msginfo {

/* Synchronize the request/response if needed */
struct completion waitevent;
struct vmbus_channel *waiting_channel;
union {
struct vmbus_channel_version_supported version_supported;
struct vmbus_channel_open_result open_result;
Expand Down

0 comments on commit 491dcca

Please sign in to comment.