}
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;
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;
return ret;
init_completion(&msginfo->waitevent);
+ msginfo->waiting_channel = channel;
gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
}
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;
return -ENOMEM;
init_completion(&info->waitevent);
+ info->waiting_channel = channel;
msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
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);
{ 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;
channel->rescind = true;
spin_unlock_irqrestore(&channel->lock, flags);
+ vmbus_rescind_cleanup(channel);
+
if (channel->device_obj) {
if (channel->chn_rescind_callback) {
channel->chn_rescind_callback(channel);
/* 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;