RE: FAILED: patch "[PATCH] Drivers: hv: vmbus: Fix bugs in rescind handling" failed to apply to 4.13-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> From: gregkh@xxxxxxxxxxxxxxxxxxx [mailto:gregkh@xxxxxxxxxxxxxxxxxxx]
> Sent: Sunday, October 15, 2017 6:28 AM
> To: KY Srinivasan <kys@xxxxxxxxxxxxx>; Dexuan Cui <decui@xxxxxxxxxxxxx>;
> gregkh@xxxxxxxxxxxxxxxxxxx
> Cc: stable@xxxxxxxxxxxxxxx
> Subject: FAILED: patch "[PATCH] Drivers: hv: vmbus: Fix bugs in rescind
> handling" failed to apply to 4.13-stable tree
> 
> 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 <stable@xxxxxxxxxxxxxxx>.
> 
> 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 <kys@xxxxxxxxxxxxx>
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.

    Signed-off-by: K. Y. Srinivasan <kys@xxxxxxxxxxxxx>
    Reviewed-by: Dexuan Cui <decui@xxxxxxxxxxxxx>
    Tested-by: Dexuan Cui <decui@xxxxxxxxxxxxx>
    Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

 
> ------------------ original commit in Linus's tree ------------------
> 
> From 192b2d78722ffea188e5ec6ae5d55010dce05a4b Mon Sep 17 00:00:00
> 2001
> From: "K. Y. Srinivasan" <kys@xxxxxxxxxxxxx>
> 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.
> 
> Fixes: '54a66265d675 ("Drivers: hv: vmbus: Fix rescind handling")'
> 
> Signed-off-by: K. Y. Srinivasan <kys@xxxxxxxxxxxxx>
> Reviewed-by: Dexuan Cui <decui@xxxxxxxxxxxxx>
> Cc: stable@xxxxxxxxxxxxxxx # (4.13 and above)
> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
> 
> diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
> index efd5db743319..894b67ac2cae 100644
> --- a/drivers/hv/channel.c
> +++ b/drivers/hv/channel.c
> @@ -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);
> 
> diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
> index bcbb031f7263..018d2e0f8ec5 100644
> --- a/drivers/hv/channel_mgmt.c
> +++ b/drivers/hv/channel_mgmt.c
> @@ -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);
>  	}
>  }
> 
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index a9d49f6f6501..937801ac2fe0 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -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);
> 
> diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
> index c458d7b7ad19..6431087816ba 100644
> --- a/include/linux/hyperv.h
> +++ b/include/linux/hyperv.h
> @@ -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);
>  /*





[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]