lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
 <SN6PR02MB4157C306208A6CF5478ED584D4182@SN6PR02MB4157.namprd02.prod.outlook.com>
Date: Tue, 14 Jan 2025 02:43:17 +0000
From: Michael Kelley <mhklinux@...look.com>
To: Hamza Mahfooz <hamzamahfooz@...ux.microsoft.com>,
	"linux-hyperv@...r.kernel.org" <linux-hyperv@...r.kernel.org>
CC: Boqun Feng <boqun.feng@...il.com>, Wei Liu <wei.liu@...nel.org>, "K. Y.
 Srinivasan" <kys@...rosoft.com>, Haiyang Zhang <haiyangz@...rosoft.com>,
	Dexuan Cui <decui@...rosoft.com>, "linux-kernel@...r.kernel.org"
	<linux-kernel@...r.kernel.org>
Subject: RE: [PATCH v2 1/2] drivers/hv: introduce vmbus_channel_set_cpu()

From: Hamza Mahfooz <hamzamahfooz@...ux.microsoft.com> Sent: Friday, January 10, 2025 2:00 PM
> 
> I would like to reuse target_cpu_store() within the driver. So, move
> most of it's body into vmbus_channel_set_cpu().

Need a more focused commit message.  Don't use personal pronouns
like "I".  I would suggest something like:

   The core functionality in target_cpu_store() is also needed in a
   subsequent patch for automatically changing the CPU when taking
   a CPU offline. As such, factor out the body of target_cpu_store()
   into new function vmbus_channel_set_cpu() that can also be used
   elsewhere.

   No functional change is intended.

> 
> Cc: Boqun Feng <boqun.feng@...il.com>
> Cc: Wei Liu <wei.liu@...nel.org>
> Signed-off-by: Hamza Mahfooz <hamzamahfooz@...ux.microsoft.com>
> ---
> v2: separate vmbus_channel_set_cpu() changes from
>     cpu offlining changes.
> ---
>  drivers/hv/vmbus_drv.c | 52 +++++++++++++++++++++++++-----------------
>  include/linux/hyperv.h |  1 +
>  2 files changed, 32 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index 2892b8da20a5..001e64fb8d43 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -1611,16 +1611,16 @@ static ssize_t target_cpu_show(struct vmbus_channel
> *channel, char *buf)
>  {
>  	return sprintf(buf, "%u\n", channel->target_cpu);
>  }
> -static ssize_t target_cpu_store(struct vmbus_channel *channel,
> -				const char *buf, size_t count)
> +
> +int vmbus_channel_set_cpu(struct vmbus_channel *channel, u32 target_cpu)
>  {
> -	u32 target_cpu, origin_cpu;
> -	ssize_t ret = count;
> +	u32 origin_cpu;
> +	int ret = 0;
> 
> -	if (vmbus_proto_version < VERSION_WIN10_V4_1)
> -		return -EIO;
> +	lockdep_assert_cpus_held();
> +	lockdep_assert_held(&vmbus_connection.channel_mutex);
> 
> -	if (sscanf(buf, "%uu", &target_cpu) != 1)
> +	if (vmbus_proto_version < VERSION_WIN10_V4_1)
>  		return -EIO;
> 
>  	/* Validate target_cpu for the cpumask_test_cpu() operation below. */
> @@ -1630,22 +1630,17 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
>  	if (!cpumask_test_cpu(target_cpu, housekeeping_cpumask(HK_TYPE_MANAGED_IRQ)))
>  		return -EINVAL;
> 
> -	/* No CPUs should come up or down during this. */
> -	cpus_read_lock();
> -
> -	if (!cpu_online(target_cpu)) {
> -		cpus_read_unlock();
> +	if (!cpu_online(target_cpu))
>  		return -EINVAL;
> -	}
> 
>  	/*
> -	 * Synchronizes target_cpu_store() and channel closure:
> +	 * Synchronizes vmbus_channel_set_cpu() and channel closure:
>  	 *
>  	 * { Initially: state = CHANNEL_OPENED }
>  	 *
>  	 * CPU1				CPU2
>  	 *
> -	 * [target_cpu_store()]		[vmbus_disconnect_ring()]
> +	 * [vmbus_channel_set_cpu()]	[vmbus_disconnect_ring()]
>  	 *
>  	 * LOCK channel_mutex		LOCK channel_mutex
>  	 * LOAD r1 = state		LOAD r2 = state
> @@ -1660,7 +1655,6 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
>  	 * Note.  The host processes the channel messages "sequentially", in
>  	 * the order in which they are received on a per-partition basis.
>  	 */
> -	mutex_lock(&vmbus_connection.channel_mutex);
> 
>  	/*
>  	 * Hyper-V will ignore MODIFYCHANNEL messages for "non-open" channels;
> @@ -1668,17 +1662,17 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
>  	 */
>  	if (channel->state != CHANNEL_OPENED_STATE) {
>  		ret = -EIO;
> -		goto cpu_store_unlock;
> +		goto end;
>  	}
> 
>  	origin_cpu = channel->target_cpu;
>  	if (target_cpu == origin_cpu)
> -		goto cpu_store_unlock;
> +		goto end;
> 
>  	if (vmbus_send_modifychannel(channel,
>  				     hv_cpu_number_to_vp_number(target_cpu))) {
>  		ret = -EIO;
> -		goto cpu_store_unlock;
> +		goto end;
>  	}
> 
>  	/*
> @@ -1708,9 +1702,25 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
>  				origin_cpu, target_cpu);
>  	}
> 
> -cpu_store_unlock:
> -	mutex_unlock(&vmbus_connection.channel_mutex);
> +end:
> +	return ret;
> +}
> +
> +static ssize_t target_cpu_store(struct vmbus_channel *channel,
> +				const char *buf, size_t count)
> +{
> +	ssize_t ret = count;
> +	u32 target_cpu;
> +
> +	if (sscanf(buf, "%uu", &target_cpu) != 1)
> +		return -EIO;
> +
> +	mutex_lock(&vmbus_connection.channel_mutex);
> +	cpus_read_lock();

These locks are in the wrong order.  Must do cpus_read_lock()
first, then lock the channel_mutex, to be consistent with the
pattern in hv_synic_cleanup(), which is entered with
cpus_read_lock() already held.

Michael

> +	ret = vmbus_channel_set_cpu(channel, target_cpu);
>  	cpus_read_unlock();
> +	mutex_unlock(&vmbus_connection.channel_mutex);
> +
>  	return ret;
>  }
>  static VMBUS_CHAN_ATTR(cpu, 0644, target_cpu_show, target_cpu_store);
> diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
> index 02a226bcf0ed..25e9e982f1b0 100644
> --- a/include/linux/hyperv.h
> +++ b/include/linux/hyperv.h
> @@ -1670,6 +1670,7 @@ int vmbus_send_tl_connect_request(const guid_t
> *shv_guest_servie_id,
>  				  const guid_t *shv_host_servie_id);
>  int vmbus_send_modifychannel(struct vmbus_channel *channel, u32 target_vp);
>  void vmbus_set_event(struct vmbus_channel *channel);
> +int vmbus_channel_set_cpu(struct vmbus_channel *channel, u32 target_cpu);
> 
>  /* Get the start of the ring buffer. */
>  static inline void *
> --
> 2.47.1
> 


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ