Drivers: hv: vmbus: Miscellaneous fixes
Subsystems (2)
cover Drivers: hv: vmbus: Miscellaneous fixes
From: "K. Y. Srinivasan" <[email protected]>
Miscellaneous fixes.
Dexuan Cui (2):
Drivers: hv: vmbus: check the creation_status in
vmbus_establish_gpadl()
Drivers: hv: vmbus: offload the handling of channels to two workqueues
drivers/hv/channel.c | 8 ++ drivers/hv/channel_mgmt.c | 188 +++++++++++++++++++++++++------------- drivers/hv/connection.c | 24 ++++- drivers/hv/hyperv_vmbus.h | 7 ++ include/linux/hyperv.h | 7 ++ 5 files changed, 169 insertions(+), 65 deletions(-)
Signature · 1 line
2.19.1
PATCH 1/2 Drivers: hv: vmbus: check the creation_status in vmbus_establish_gpadl()
From: Dexuan Cui <[email protected]>
This is a longstanding issue: if the vmbus upper-layer drivers try to consume too many GPADLs, the host may return with an error 0xC0000044 (STATUS_QUOTA_EXCEEDED), but currently we forget to check the creation_status, and hence we can pass an invalid GPADL handle into the OPEN_CHANNEL message, and get an error code 0xc0000225 in open_info->response.open_result.status, and finally we hang in vmbus_open() -> "goto error_free_info" -> vmbus_teardown_gpadl().
With this patch, we can exit gracefully on STATUS_QUOTA_EXCEEDED.
--- drivers/hv/channel.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/hv/channel.c +8 -0
@@ -516,6 +516,14 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, }wait_for_completion (&msginfo->waitevent); +if (msginfo->response.gpadl_created.creation_status !=0 ) { +pr_err ("Failed to establish GPADL: err = 0x%x\n" , + msginfo->response.gpadl_created.creation_status); + + ret = -EDQUOT ; + goto cleanup; + } +if (channel->rescind) { ret = -ENODEV ; goto cleanup;
Signature · 1 line
2.19.1
PATCH 2/2 Drivers: hv: vmbus: offload the handling of channels to two workqueues
From: Dexuan Cui <[email protected]>
vmbus_process_offer() mustn't call channel->sc_creation_callback() directly for sub-channels, because sc_creation_callback() -> vmbus_open() may never get the host's response to the OPEN_CHANNEL message (the host may rescind a channel at any time, e.g. in the case of hot removing a NIC), and vmbus_onoffer_rescind() may not wake up the vmbus_open() as it's blocked due to a non-zero vmbus_connection.offer_in_progress, and finally we have a deadlock.
The above is also true for primary channels, if the related device drivers use sync probing mode by default.
And, usually the handling of primary channels and sub-channels can depend on each other, so we should offload them to different workqueues to avoid possible deadlock, e.g. in sync-probing mode, NIC1's netvsc_subchan_work() can race with NIC2's netvsc_probe() -> rtnl_lock(), and causes deadlock: the former gets the rtnl_lock and waits for all the sub-channels to appear, but the latter can't get the rtnl_lock and this blocks the handling of sub-channels.
The patch can fix the multiple-NIC deadlock described above for v3.x kernels (e.g. RHEL 7.x) which don't support async-probing of devices, and v4.4, v4.9, v4.14 and v4.18 which support async-probing but don't enable async-probing for Hyper-V drivers (yet).
The patch can also fix the hang issue in sub-channel's handling described above for all versions of kernels, including v4.19 and v4.20-rc3.
So the patch should be applied to all the existing kernels.
--- drivers/hv/channel_mgmt.c | 188 +++++++++++++++++++++++++------------- drivers/hv/connection.c | 24 ++++- drivers/hv/hyperv_vmbus.h | 7 ++ include/linux/hyperv.h | 7 ++ 4 files changed, 161 insertions(+), 65 deletions(-)
drivers/hv/channel_mgmt.c +126 -62
@@ -434,60 +434,16 @@ void vmbus_free_channels(void) } } -/* -* vmbus_process_offer - Process the offer by creating a channel/device -* associated with this offer -*/ -static void vmbus_process_offer (struct vmbus_channel *newchannel) +/* Note: the function can run concurrently for primary/sub channels. */ +static void vmbus_add_channel_work (struct work_struct *work) { -struct vmbus_channel *channel; -bool fnew = true; +struct vmbus_channel *newchannel = + container_of(work, struct vmbus_channel, add_channel_work); +struct vmbus_channel *primary_channel = newchannel->primary_channel;unsigned long flags;u16 dev_type;int ret; -/* Make sure this is a new offer */ -mutex_lock (&vmbus_connection.channel_mutex); - -/* -* Now that we have acquired the channel_mutex, -* we can release the potentially racing rescind thread. -*/ -atomic_dec (&vmbus_connection.offer_in_progress); - -list_for_each_entry (channel, &vmbus_connection.chn_list, listentry) { -if (!uuid_le_cmp (channel->offermsg.offer.if_type, - newchannel->offermsg.offer.if_type) && - !uuid_le_cmp (channel->offermsg.offer.if_instance, - newchannel->offermsg.offer.if_instance)) { - fnew = false; -break ; - } - } - -if (fnew) -list_add_tail (&newchannel->listentry, - &vmbus_connection.chn_list); - -mutex_unlock (&vmbus_connection.channel_mutex); - -if (!fnew) { -/* -* Check to see if this is a sub-channel. -*/ -if (newchannel->offermsg.offer.sub_channel_index !=0 ) { -/* -* Process the sub-channel. -*/ - newchannel->primary_channel = channel; -spin_lock_irqsave (&channel->lock, flags); -list_add_tail (&newchannel->sc_list, &channel->sc_list); -spin_unlock_irqrestore (&channel->lock, flags); - }else { - goto err_free_chan; - } - } - dev_type =hv_get_dev_type (newchannel);init_vp_index (newchannel, dev_type);
@@ -505,27 +461,26 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)/* * This state is used to indicate a successful open * so that when we do close the channel normally, we -* can cleanup properly +* can cleanup properly. */ newchannel->state =CHANNEL_OPEN_STATE ; -if (!fnew) { -struct hv_device *dev - = newchannel->primary_channel->device_obj; +if (primary_channel !=NULL ) { +/* newchannel is a sub-channel. */ +struct hv_device *dev = primary_channel->device_obj;if (vmbus_add_channel_kobj (dev, newchannel)) - goto err_free_chan; + goto err_deq_chan; + +if (primary_channel->sc_creation_callback !=NULL ) + primary_channel->sc_creation_callback (newchannel); -if (channel->sc_creation_callback !=NULL ) - channel->sc_creation_callback (newchannel); newchannel->probe_done = true;return ; }/* -* Start the process of binding this offer to the driver -* We need to set the DeviceObject field before calling -* vmbus_child_dev_add() +* Start the process of binding the primary channel to the driver */ newchannel->device_obj = vmbus_device_create( &newchannel->offermsg.offer.if_type,
@@ -554,13 +509,28 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) err_deq_chan:mutex_lock (&vmbus_connection.channel_mutex); -list_del (&newchannel->listentry); + +/* +* We need to set the flag, otherwise +* vmbus_onoffer_rescind() can be blocked. +*/ + newchannel->probe_done = true; + +if (primary_channel ==NULL ) { +list_del (&newchannel->listentry); + }else { +spin_lock_irqsave (&primary_channel->lock, flags); +list_del (&newchannel->sc_list); +spin_unlock_irqrestore (&primary_channel->lock, flags); + } +mutex_unlock (&vmbus_connection.channel_mutex);if (newchannel->target_cpu !=get_cpu ()) {put_cpu ();smp_call_function_single (newchannel->target_cpu, - percpu_channel_deq, newchannel, true); + percpu_channel_deq, + newchannel, true); }else {percpu_channel_deq (newchannel);put_cpu ();
@@ -568,14 +538,104 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)vmbus_release_relid (newchannel->offermsg.child_relid); -err_free_chan:free_channel (newchannel); } +/* +* vmbus_process_offer - Process the offer by creating a channel/device +* associated with this offer +*/ +static void vmbus_process_offer (struct vmbus_channel *newchannel) +{ +struct vmbus_channel *channel; +struct workqueue_struct *wq; +unsigned long flags; +bool fnew = true; + +mutex_lock (&vmbus_connection.channel_mutex); + +/* +* Now that we have acquired the channel_mutex, +* we can release the potentially racing rescind thread. +*/ +atomic_dec (&vmbus_connection.offer_in_progress); + +list_for_each_entry (channel, &vmbus_connection.chn_list, listentry) { +if (!uuid_le_cmp (channel->offermsg.offer.if_type, + newchannel->offermsg.offer.if_type) && + !uuid_le_cmp (channel->offermsg.offer.if_instance, + newchannel->offermsg.offer.if_instance)) { + fnew = false; +break ; + } + } + +if (fnew) +list_add_tail (&newchannel->listentry, + &vmbus_connection.chn_list); +else { +/* +* Check to see if this is a valid sub-channel. +*/ +if (newchannel->offermsg.offer.sub_channel_index ==0 ) { +mutex_unlock (&vmbus_connection.channel_mutex); +/* +* Don't call free_channel(), because newchannel->kobj +* is not initialized yet. +*/ +kfree (newchannel); +WARN_ON_ONCE (1 ); +return ; + } +/* +* Process the sub-channel. +*/ + newchannel->primary_channel = channel; +spin_lock_irqsave (&channel->lock, flags); +list_add_tail (&newchannel->sc_list, &channel->sc_list); +spin_unlock_irqrestore (&channel->lock, flags); + } + +mutex_unlock (&vmbus_connection.channel_mutex); + +/* +* vmbus_process_offer() mustn't call channel->sc_creation_callback() +* directly for sub-channels, because sc_creation_callback() -> +* vmbus_open() may never get the host's response to the +* OPEN_CHANNEL message (the host may rescind a channel at any time, +* e.g. in the case of hot removing a NIC), and vmbus_onoffer_rescind() +* may not wake up the vmbus_open() as it's blocked due to a non-zero +* vmbus_connection.offer_in_progress, and finally we have a deadlock. +* +* The above is also true for primary channels, if the related device +* drivers use sync probing mode by default. +* +* And, usually the handling of primary channels and sub-channels can +* depend on each other, so we should offload them to different +* workqueues to avoid possible deadlock, e.g. in sync-probing mode, +* NIC1's netvsc_subchan_work() can race with NIC2's netvsc_probe() -> +* rtnl_lock(), and causes deadlock: the former gets the rtnl_lock +* and waits for all the sub-channels to appear, but the latter +* can't get the rtnl_lock and this blocks the handling of +* sub-channels. +*/ +INIT_WORK (&newchannel->add_channel_work, vmbus_add_channel_work); + wq = fnew ? vmbus_connection.handle_primary_chan_wq : + vmbus_connection.handle_sub_chan_wq; +queue_work (wq, &newchannel->add_channel_work); +} +/* * We use this state to statically distribute the channel interrupt load. */ static int next_numa_node_id; +/* +* init_vp_index() accesses global variables like next_numa_node_id, and +* it can run concurrently for primary channels and sub-channels: see +* vmbus_process_offer(), so we need the lock to protect the global +* variables. +*/ +static DEFINE_SPINLOCK (bind_channel_to_cpu_lock);/* * Starting with Win8, we can statically distribute the incoming
@@ -611,6 +671,8 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)return ; } +spin_lock (&bind_channel_to_cpu_lock); +/* * Based on the channel affinity policy, we will assign the NUMA * nodes.
@@ -693,6 +755,8 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) channel->target_cpu = cur_cpu; channel->target_vp =hv_cpu_number_to_vp_number (cur_cpu); +spin_unlock (&bind_channel_to_cpu_lock); +free_cpumask_var (available_mask); }
drivers/hv/connection.c +21 -3
@@ -190,6 +190,20 @@ int vmbus_connect(void) goto cleanup; } + vmbus_connection.handle_primary_chan_wq = +create_workqueue ("hv_pri_chan" ); +if (!vmbus_connection.handle_primary_chan_wq) { + ret = -ENOMEM ; + goto cleanup; + } + + vmbus_connection.handle_sub_chan_wq = +create_workqueue ("hv_sub_chan" ); +if (!vmbus_connection.handle_sub_chan_wq) { + ret = -ENOMEM ; + goto cleanup; + } +INIT_LIST_HEAD (&vmbus_connection.chn_msg_list);spin_lock_init (&vmbus_connection.channelmsg_lock);
@@ -280,10 +294,14 @@ void vmbus_disconnect(void)*/ vmbus_initiate_unload (false); -if (vmbus_connection.work_queue) { -drain_workqueue (vmbus_connection.work_queue); +if (vmbus_connection.handle_sub_chan_wq) +destroy_workqueue (vmbus_connection.handle_sub_chan_wq); + +if (vmbus_connection.handle_primary_chan_wq) +destroy_workqueue (vmbus_connection.handle_primary_chan_wq); + +if (vmbus_connection.work_queue)destroy_workqueue (vmbus_connection.work_queue); - }if (vmbus_connection.int_page) {free_pages ((unsigned long )vmbus_connection.int_page,0 );
drivers/hv/hyperv_vmbus.h +7 -0
@@ -333,7 +333,14 @@ struct vmbus_connection {struct list_head chn_list;struct mutex channel_mutex; +/* +* An offer message is handled first on the work_queue, and then +* is further handled on handle_primary_chan_wq or +* handle_sub_chan_wq. +*/ struct workqueue_struct *work_queue; +struct workqueue_struct *handle_primary_chan_wq; +struct workqueue_struct *handle_sub_chan_wq; };
include/linux/hyperv.h +7 -0
@@ -896,6 +896,13 @@ struct vmbus_channel {bool probe_done; +/* +* We must offload the handling of the primary/sub channels +* from the single-threaded vmbus_connection.work_queue to +* two different workqueue, otherwise we can block +* vmbus_connection.work_queue and hang: see vmbus_process_offer(). +*/ +struct work_struct add_channel_work; };static inline bool is_hvsock_channel (const struct vmbus_channel *c)
Signature · 1 line
2.19.1
Sasha Levin
maintainerRe: [PATCH 2/2] Drivers: hv: vmbus: offload the handling of channels to two workqueues
Quoted 31 lines · On Mon, Nov 26, 2018 at 02:29:57AM +0000, [email protected] wrote:
From: Dexuan Cui <[email protected]>
vmbus_process_offer()mustn't callchannel->sc_creation_callback()directly for sub-channels, becausesc_creation_callback()->vmbus_open()may never get the host's response to theOPEN_CHANNELmessage (the host may rescind a channel at any time, e.g. in the case of hot removing a NIC), andvmbus_onoffer_rescind()may not wake up thevmbus_open()as it's blocked due to a non-zero vmbus_connection.offer_in_progress, and finally we have a deadlock.The above is also true for primary channels, if the related device drivers use sync probing mode by default.
And, usually the handling of primary channels and sub-channels can depend on each other, so we should offload them to different workqueues to avoid possible deadlock, e.g. in sync-probing mode, NIC1's
netvsc_subchan_work()can race with NIC2'snetvsc_probe()->rtnl_lock(), and causes deadlock: the former gets thertnl_lockand waits for all the sub-channels to appear, but the latter can't get thertnl_lockand this blocks the handling of sub-channels.The patch can fix the multiple-NIC deadlock described above for v3.x kernels (e.g. RHEL 7.x) which don't support async-probing of devices, and v4.4, v4.9, v4.14 and v4.18 which support async-probing but don't enable async-probing for Hyper-V drivers (yet).
The patch can also fix the hang issue in sub-channel's handling described above for all versions of kernels, including v4.19 and v4.20-rc3.
So the patch should be applied to all the existing kernels.
Quoted 7 lines
Fixes 8195b1396ec8 ("hv_netvsc: fix deadlock on hotplug")Cc Stephen Hemminger <[email protected]>Cc K. Y. Srinivasan <[email protected]>Cc Haiyang Zhang <[email protected]>Signed-off-by Dexuan Cui <[email protected]>Signed-off-by K. Y. Srinivasan <[email protected]>
This patch doesn't apply on next/linus/char-misc; there seems to be a missing patch that touches vmbus_process_offer() which isn't a part of this series.
--
Thanks,
Sasha
Greg KH
maintainerRe: [PATCH 2/2] Drivers: hv: vmbus: offload the handling of channels to two workqueues
In reply to [email protected]Quoted 38 lines · On Mon, Nov 26, 2018 at 02:29:57AM +0000, [email protected] wrote:
From: Dexuan Cui <[email protected]>
vmbus_process_offer()mustn't callchannel->sc_creation_callback()directly for sub-channels, becausesc_creation_callback()->vmbus_open()may never get the host's response to theOPEN_CHANNELmessage (the host may rescind a channel at any time, e.g. in the case of hot removing a NIC), andvmbus_onoffer_rescind()may not wake up thevmbus_open()as it's blocked due to a non-zero vmbus_connection.offer_in_progress, and finally we have a deadlock.The above is also true for primary channels, if the related device drivers use sync probing mode by default.
And, usually the handling of primary channels and sub-channels can depend on each other, so we should offload them to different workqueues to avoid possible deadlock, e.g. in sync-probing mode, NIC1's
netvsc_subchan_work()can race with NIC2'snetvsc_probe()->rtnl_lock(), and causes deadlock: the former gets thertnl_lockand waits for all the sub-channels to appear, but the latter can't get thertnl_lockand this blocks the handling of sub-channels.The patch can fix the multiple-NIC deadlock described above for v3.x kernels (e.g. RHEL 7.x) which don't support async-probing of devices, and v4.4, v4.9, v4.14 and v4.18 which support async-probing but don't enable async-probing for Hyper-V drivers (yet).
The patch can also fix the hang issue in sub-channel's handling described above for all versions of kernels, including v4.19 and v4.20-rc3.
So the patch should be applied to all the existing kernels.
Fixes 8195b1396ec8 ("hv_netvsc: fix deadlock on hotplug")Cc Stephen Hemminger <[email protected]>Cc K. Y. Srinivasan <[email protected]>Cc Haiyang Zhang <[email protected]>Signed-off-by Dexuan Cui <[email protected]>Signed-off-by K. Y. Srinivasan <[email protected]>
Quoted 6 lines
--- drivers/hv/channel_mgmt.c | 188 +++++++++++++++++++++++++------------- drivers/hv/connection.c | 24 ++++- drivers/hv/hyperv_vmbus.h | 7 ++ include/linux/hyperv.h | 7 ++ 4 files changed, 161 insertions(+), 65 deletions(-)
As Sasha pointed out, this patch does not even apply :(
Dexuan Cui
maintainerRE: [PATCH 2/2] Drivers: hv: vmbus: offload the handling of channels to two workqueues
Quoted 4 lines
From: devel <[email protected]> On Behalf Of Greg KH
Sent: Monday, November 26, 2018 11:35 AM
As Sasha pointed out, this patch does not even apply :(
Sorry, I'll rebase to char-misc's char-misc-testing branch, which has had one of the patches, i.e.
4d3c5c69191f ("Drivers: hv: vmbus: Remove the useless API vmbus_get_outgoing_channel()")
Thanks,
-- Dexuan
RE: [PATCH 2/2] Drivers: hv: vmbus: offload the handling of channels to two workqueues
In reply to Greg KHQuoted 55 lines
-----Original Message-----
From: Greg KH <[email protected]>
Sent: Monday, November 26, 2018 11:35 AM
To: KY Srinivasan <[email protected]>
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Stephen Hemminger <[email protected]>; Michael Kelley <[email protected]>; vkuznets <[email protected]>; Haiyang Zhang <[email protected]>; [email protected]
Subject: Re: [PATCH 2/2] Drivers: hv: vmbus: offload the handling of channels to two workqueuesQuoted 38 lines · On Mon, Nov 26, 2018 at 02:29:57AM +0000, [email protected] wrote:
From: Dexuan Cui <[email protected]>
vmbus_process_offer()mustn't callchannel->sc_creation_callback()directly for sub-channels, becausesc_creation_callback()->vmbus_open()may never get the host's response to theOPEN_CHANNELmessage (the host may rescind a channel at any time, e.g. in the case of hot removing a NIC), andvmbus_onoffer_rescind()may not wake up thevmbus_open()as it's blocked due to a non-zero vmbus_connection.offer_in_progress, and finally we have a deadlock.The above is also true for primary channels, if the related device drivers use sync probing mode by default.
And, usually the handling of primary channels and sub-channels can depend on each other, so we should offload them to different workqueues to avoid possible deadlock, e.g. in sync-probing mode, NIC1's
netvsc_subchan_work()can race with NIC2'snetvsc_probe()->rtnl_lock(), and causes deadlock: the former gets thertnl_lockand waits for all the sub-channels to appear, but the latter can't get thertnl_lockand this blocks the handling of sub-channels.The patch can fix the multiple-NIC deadlock described above for v3.x kernels (e.g. RHEL 7.x) which don't support async-probing of devices, and v4.4, v4.9, v4.14 and v4.18 which support async-probing but don't enable async-probing for Hyper-V drivers (yet).
The patch can also fix the hang issue in sub-channel's handling described above for all versions of kernels, including v4.19 and v4.20-rc3.
So the patch should be applied to all the existing kernels.
Fixes 8195b1396ec8 ("hv_netvsc: fix deadlock on hotplug")Cc Stephen Hemminger <[email protected]>Cc K. Y. Srinivasan <[email protected]>Cc Haiyang Zhang <[email protected]>Signed-off-by Dexuan Cui <[email protected]>Signed-off-by K. Y. Srinivasan <[email protected]>Quoted 2 lines
--- drivers/hv/channel_mgmt.c | 188 +++++++++++++++++++++++++---------
Quoted 7 lines
----
Quoted 4 lines
drivers/hv/connection.c | 24 ++++- drivers/hv/hyperv_vmbus.h | 7 ++ include/linux/hyperv.h | 7 ++ 4 files changed, 161 insertions(+), 65 deletions(-)As Sasha pointed out, this patch does not even apply :(
Sorry about that. These patches applied cleanly on my tree (misc-next).
This series is to be applied on top of
patch 0001-Drivers-hv-vmbus-Remove-the-useless-API-vmbus_get_ou.patch
While the patch 0001-Drivers-hv-vmbus-Remove-the-useless-API-vmbus_get_ou.patch has been committed to the char-misc-testing branch, it is not in the misc-linus branch and that is the reason for this problem.
Regards,
K. Y
Quoted 1 line
A message that is not in the archive (sent off-list or not yet received): [email protected]
Dexuan Cui
maintainerRE: [PATCH 1/2] Drivers: hv: vmbus: check the creation_status in vmbus_establish_gpadl()
Quoted 18 lines
From: Sasha Levin <[email protected]>
Sent: Monday, November 26, 2018 1:53 AM
Hi,[This is an automated email]
This commit has been processed because it contains a -stable tag. The stable tag indicates that it's relevant for the following trees: all
The bot has tested the following trees: v4.19.4, v4.14.83, v4.9.140, v4.4.164, v3.18.126.
v4.19.4: Build OK!
v4.14.83: Build OK!
v4.9.140: Build OK!
v4.4.164: Failed to apply! Possible dependencies:
v3.18.126: Failed to apply! Possible dependencies:
Quoted 3 lines
How should we proceed with this patch?
Sasha
Hi Sasha,
Please see the attached patch, which is a rebase for both v4.4.164 and v3.18.126.
Thanks,
--Dexuan
From 038481c8b771bd22e40cd5d622dc147d486b97c8 Mon Sep 17 00:00:00 2001
From: Dexuan Cui <[email protected]>
Date: Mon, 26 Nov 2018 02:29:56 +0000
Subject: [PATCH] Drivers: hv: vmbus: check the creation_status in
vmbus_establish_gpadl()
This is a longstanding issue: if the vmbus upper-layer drivers try to consume too many GPADLs, the host may return with an error 0xC0000044 (STATUS_QUOTA_EXCEEDED), but currently we forget to check the creation_status, and hence we can pass an invalid GPADL handle into the OPEN_CHANNEL message, and get an error code 0xc0000225 in open_info->response.open_result.status, and finally we hang in vmbus_open() -> "goto error_free_info" -> vmbus_teardown_gpadl().
With this patch, we can exit gracefully on STATUS_QUOTA_EXCEEDED.
--- drivers/hv/channel.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/hv/channel.c +8 -0
@@ -424,6 +424,14 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, }wait_for_completion (&msginfo->waitevent); +if (msginfo->response.gpadl_created.creation_status !=0 ) { +pr_err ("Failed to establish GPADL: err = 0x%x\n" , + msginfo->response.gpadl_created.creation_status); + + ret = -EDQUOT ; + goto cleanup; + } +/* At this point, we received the gpadl created msg */ *gpadl_handle = gpadlmsg->gpadl;
Signature · 1 line
2.7.4