FAILED: patch "[PATCH] Drivers: hv: vmbus: Fix bugs in rescind handling" failed to apply to 4.13-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.13-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
192b2d78722ffea188e5ec6ae5d55010dce05a4bMon Sep 17 00:00:00 2001
From: "K. Y. Srinivasan" <[email protected]>
Date: Fri, 29 Sep 2017 21:09:36 -0700
Subject: [PATCH] Drivers: hv: vmbus: Fix bugs in rescind handling
This patch addresses the following bugs in the current rescind handling code:
1. Fixes a race condition where we may be invoking hv_process_channel_removal() on an already freed channel.
2. Prevents indefinite wait when rescinding sub-channels by correctly setting the probe_complete state.
I would like to thank Dexuan for patiently reviewing earlier versions of this patch and identifying many of the issues fixed here.
Greg, please apply this to 4.14-final.
drivers/hv/channel.c +3 -3
@@ -640,6 +640,7 @@ void vmbus_close(struct vmbus_channel *channel)*/ return ; } +mutex_lock (&vmbus_connection.channel_mutex);/* * Close all the sub-channels first and then close the * primary channel.
@@ -648,16 +649,15 @@ void vmbus_close(struct vmbus_channel *channel) cur_channel = list_entry(cur, struct vmbus_channel, sc_list);vmbus_close_internal (cur_channel);if (cur_channel->rescind) { -mutex_lock (&vmbus_connection.channel_mutex); -hv_process_channel_removal (cur_channel, +hv_process_channel_removal ( cur_channel->offermsg.child_relid); -mutex_unlock (&vmbus_connection.channel_mutex); } }/* * Now close the primary. */ vmbus_close_internal (channel); +mutex_unlock (&vmbus_connection.channel_mutex); }EXPORT_SYMBOL_GPL (vmbus_close);
drivers/hv/channel_mgmt.c +18 -19
@@ -159,7 +159,7 @@ static void vmbus_rescind_cleanup(struct vmbus_channel *channel)spin_lock_irqsave (&vmbus_connection.channelmsg_lock, flags); - + channel->rescind = true;list_for_each_entry (msginfo, &vmbus_connection.chn_msg_list, msglistentry) {
@@ -381,14 +381,21 @@ static void vmbus_release_relid(u32 relid) true); } -void hv_process_channel_removal (struct vmbus_channel *channel,u32 relid) +void hv_process_channel_removal (u32 relid) {unsigned long flags; -struct vmbus_channel *primary_channel; +struct vmbus_channel *primary_channel, *channel; -BUG_ON (!channel->rescind);BUG_ON (!mutex_is_locked (&vmbus_connection.channel_mutex)); +/* +* Make sure channel is valid as we may have raced. +*/ + channel =relid2channel (relid); +if (!channel) +return ; + +BUG_ON (!channel->rescind);if (channel->target_cpu !=get_cpu ()) {put_cpu (); smp_call_function_single(channel->target_cpu,
@@ -515,6 +522,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)if (!fnew) {if (channel->sc_creation_callback !=NULL ) channel->sc_creation_callback (newchannel); + newchannel->probe_done = true;return ; }
@@ -834,7 +842,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) {struct vmbus_channel_rescind_offer *rescind;struct vmbus_channel *channel; -unsigned long flags;struct device *dev; rescind = (struct vmbus_channel_rescind_offer *)hdr;
@@ -873,16 +880,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)return ; } -spin_lock_irqsave (&channel->lock, flags); - channel->rescind = true; -spin_unlock_irqrestore (&channel->lock, flags); - -/* -* Now that we have posted the rescind state, perform -* rescind related cleanup. -*/ -vmbus_rescind_cleanup (channel); -/* * Now wait for offer handling to complete. */
@@ -901,6 +898,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)if (channel->device_obj) {if (channel->chn_rescind_callback) { channel->chn_rescind_callback (channel); +vmbus_rescind_cleanup (channel);return ; }/*
@@ -909,6 +907,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)*/ dev =get_device (&channel->device_obj->device);if (dev) { +vmbus_rescind_cleanup (channel);vmbus_device_unregister (channel->device_obj);put_device (dev); }
@@ -921,16 +920,16 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)* 1. Close all sub-channels first * 2. Then close the primary channel. */ +mutex_lock (&vmbus_connection.channel_mutex); +vmbus_rescind_cleanup (channel);if (channel->state ==CHANNEL_OPEN_STATE ) {/* * The channel is currently not open; * it is safe for us to cleanup the channel. */ -mutex_lock (&vmbus_connection.channel_mutex); -hv_process_channel_removal (channel, - channel->offermsg.child_relid); -mutex_unlock (&vmbus_connection.channel_mutex); +hv_process_channel_removal (rescind->child_relid); } +mutex_unlock (&vmbus_connection.channel_mutex); } }
drivers/hv/vmbus_drv.c +1 -2
@@ -768,8 +768,7 @@ static void vmbus_device_release(struct device *device)struct vmbus_channel *channel = hv_dev->channel;mutex_lock (&vmbus_connection.channel_mutex); -hv_process_channel_removal (channel, - channel->offermsg.child_relid); +hv_process_channel_removal (channel->offermsg.child_relid);mutex_unlock (&vmbus_connection.channel_mutex);kfree (hv_dev);
include/linux/hyperv.h +1 -1
@@ -1403,7 +1403,7 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf, const int *srv_version, int srv_vercnt, int *nego_fw_version, int *nego_srv_version); -void hv_process_channel_removal (struct vmbus_channel *channel,u32 relid); +void hv_process_channel_removal (u32 relid);void vmbus_setevent (struct vmbus_channel *channel);/*
Quoted 8 lines
From: [email protected] [mailto:[email protected]]
Sent: Sunday, October 15, 2017 6:28 AM
To: KY Srinivasan <[email protected]>; Dexuan Cui <[email protected]>; [email protected]
Cc: [email protected]
Subject: FAILED: patch "[PATCH] Drivers: hv: vmbus: Fix bugs in rescind handling" failed to apply to 4.13-stable tree
Quoted 8 lines
The patch below does not apply to the 4.13-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.thanks,
greg k-h
Hi Greg,
Before applying this patch (192b2d7872), please cherry-pick the prerequisite patch (6f3d791f30) in Linus's tree.
As I tested just now, the 2 patches applied cleanly on linux-4.13.y, which
Means v4.13.7 today.
Thanks,
-- Dexuan
commit 6f3d791f300618caf82a2be0c27456edd76d5164
Author: K. Y. Srinivasan <[email protected]> Date: Fri Aug 11 10:03:59 2017 -0700
Drivers: hv: vmbus: Fix rescind handling issues
This patch handles the following issues that were observed when we are handling racing channel offer message and rescind message for the same offer:
1. Since the host does not respond to messages on a rescinded channel, in the current code, we could be indefinitely blocked on the vmbus_open() call.
2. When a rescinded channel is being closed, if there is a pending interrupt on the channel, we could end up freeing the channel that the interrupt handler would run on.
Quoted 203 lines
------------------ original commit in Linus's tree ------------------
From
192b2d78722ffea188e5ec6ae5d55010dce05a4bMon Sep 17 00:00:00 2001
From: "K. Y. Srinivasan" <[email protected]>
Date: Fri, 29 Sep 2017 21:09:36 -0700
Subject: [PATCH] Drivers: hv: vmbus: Fix bugs in rescind handlingThis patch addresses the following bugs in the current rescind handling code:
1. Fixes a race condition where we may be invoking
hv_process_channel_removal()
on an already freed channel.2. Prevents indefinite wait when rescinding sub-channels by correctly setting the
probe_completestate.I would like to thank Dexuan for patiently reviewing earlier versions of this patch and identifying many of the issues fixed here.
Greg, please apply this to 4.14-final.
Fixes '54a66265d675 ("Drivers: hv: vmbus: Fix rescind handling")'Signed-off-by K. Y. Srinivasan <[email protected]>Reviewed-by Dexuan Cui <[email protected]>Cc [email protected] # (4.13 and above)Signed-off-by Greg Kroah-Hartman <[email protected]>drivers/hv/channel.c +3
-3@@ -640,6 +640,7 @@ void vmbus_close(struct vmbus_channel *channel)*/ return ; } +mutex_lock (&vmbus_connection.channel_mutex);/* * Close all the sub-channels first and then close the * primary channel. @@ -648,16 +649,15 @@ void vmbus_close(struct vmbus_channel *channel) cur_channel = list_entry(cur, struct vmbus_channel, sc_list);vmbus_close_internal (cur_channel);if (cur_channel->rescind) { -mutex_lock (&vmbus_connection.channel_mutex); -hv_process_channel_removal (cur_channel, +hv_process_channel_removal ( cur_channel->offermsg.child_relid); -mutex_unlock (&vmbus_connection.channel_mutex); } }/* * Now close the primary. */ vmbus_close_internal (channel); +mutex_unlock (&vmbus_connection.channel_mutex); }EXPORT_SYMBOL_GPL (vmbus_close);drivers/hv/channel_mgmt.c +12
-5@@ -159,7 +159,7 @@ static void vmbus_rescind_cleanup(struct vmbus_channel *channel) spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - + channel->rescind = true;list_for_each_entry (msginfo, &vmbus_connection.chn_msg_list, msglistentry) {@@ -381,14 +381,21 @@ static void vmbus_release_relid(u32 relid) true); } -void hv_process_channel_removal (struct vmbus_channel *channel,u32 relid) +void hv_process_channel_removal (u32 relid) {unsigned long flags; -struct vmbus_channel *primary_channel; +struct vmbus_channel *primary_channel, *channel; -BUG_ON (!channel->rescind);BUG_ON (!mutex_is_locked (&vmbus_connection.channel_mutex)); +/* +* Make sure channel is valid as we may have raced. +*/ + channel =relid2channel (relid); +if (!channel) +return ; + +BUG_ON (!channel->rescind);if (channel->target_cpu !=get_cpu ()) {put_cpu (); smp_call_function_single(channel->target_cpu,@@ -515,6 +522,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)if (!fnew) {if (channel->sc_creation_callback !=NULL ) channel->sc_creation_callback (newchannel); + newchannel->probe_done = true;return ; }@@ -834,7 +842,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) {struct vmbus_channel_rescind_offer *rescind;struct vmbus_channel *channel; -unsigned long flags;struct device *dev;drivers/hv/channel_mgmt.c +0
-10rescind = (struct vmbus_channel_rescind_offer *)hdr;@@ -873,16 +880,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) return; } -spin_lock_irqsave (&channel->lock, flags); - channel->rescind = true; -spin_unlock_irqrestore (&channel->lock, flags); - -/* -* Now that we have posted the rescind state, perform -* rescind related cleanup. -*/ -vmbus_rescind_cleanup (channel); -/* * Now wait for offer handling to complete. drivers/hv/channel_mgmt.c +1
-0*/ @@ -901,6 +898,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)if (channel->device_obj) {if (channel->chn_rescind_callback) { channel->chn_rescind_callback (channel); +vmbus_rescind_cleanup (channel);return ; }drivers/hv/channel_mgmt.c +1
-0/* @@ -909,6 +907,7 @@ static void vmbus_onoffer_rescind(structvmbus_channel_message_header *hdr) */ dev =get_device (&channel->device_obj->device);if (dev) { +vmbus_rescind_cleanup (channel);vmbus_device_unregister (channel->device_obj);put_device (dev);drivers/hv/channel_mgmt.c +4
-4}@@ -921,16 +920,16 @@ static void vmbus_onoffer_rescind(structvmbus_channel_message_header *hdr) * 1. Close all sub-channels first * 2. Then close the primary channel. */ +mutex_lock (&vmbus_connection.channel_mutex); +vmbus_rescind_cleanup (channel);if (channel->state ==CHANNEL_OPEN_STATE ) {/* * The channel is currently not open; * it is safe for us to cleanup the channel. */ -mutex_lock (&vmbus_connection.channel_mutex); -hv_process_channel_removal (channel, - channel->offermsg.child_relid); -mutex_unlock (&vmbus_connection.channel_mutex); +hv_process_channel_removal (rescind->child_relid); } +mutex_unlock (&vmbus_connection.channel_mutex); } }drivers/hv/vmbus_drv.c +1
-2@@ -768,8 +768,7 @@ static void vmbus_device_release(struct device *device)struct vmbus_channel *channel = hv_dev->channel;mutex_lock (&vmbus_connection.channel_mutex); -hv_process_channel_removal (channel, - channel->offermsg.child_relid); +hv_process_channel_removal (channel->offermsg.child_relid);mutex_unlock (&vmbus_connection.channel_mutex);kfree (hv_dev);include/linux/hyperv.h +1
-1@@ -1403,7 +1403,7 @@ extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, u8 *buf, const int *srv_version, int srv_vercnt, int *nego_fw_version, int *nego_srv_version); -void hv_process_channel_removal (struct vmbus_channel *channel,u32 relid); +void hv_process_channel_removal (u32 relid);void vmbus_setevent (struct vmbus_channel *channel);/*
[email protected]
maintainerQuoted 15 lines · Dexuan Cui
Quoted 15 lines
From: [email protected] [mailto:[email protected]]
Sent: Sunday, October 15, 2017 6:28 AM
To: KY Srinivasan <[email protected]>; Dexuan Cui <[email protected]>; [email protected]
Cc: [email protected]
Subject: FAILED: patch "[PATCH] Drivers: hv: vmbus: Fix bugs in rescind handling" failed to apply to 4.13-stable treeThe patch below does not apply to the 4.13-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.thanks,
Quoted 8 lines
Quoted 1 line
greg k-h
Hi Greg,
Before applying this patch (192b2d7872), please cherry-pick the prerequisite patch (6f3d791f30) in Linus's tree.As I tested just now, the 2 patches applied cleanly on linux-4.13.y, which
Means v4.13.7 today.
Ah, that worked, thanks!
greg k-h