Miscellaneous fixes/enhancements
Subsystems (3)
cover Miscellaneous fixes/enhancements
From: "K. Y. Srinivasan" <[email protected]>
Miscellaneous fixes/enhancements.
K. Y. Srinivasan (1):
Tools: hv: Fix a bug in the key delete code
Michael Kelley (1):
Drivers: hv: vmbus: Fix synic per-cpu context initialization
Stephen Hemminger (3):
vmbus: add driver_override support
uio_hv_generic: increase size of receive and send buffers
uio_hv_generic: drop #ifdef DEBUG
Documentation/ABI/testing/sysfs-bus-vmbus | 21 ++++ drivers/hv/hv.c | 15 ++- drivers/hv/vmbus_drv.c | 115 ++++++++++++++++++---- drivers/uio/uio_hv_generic.c | 7 +- include/linux/hyperv.h | 1 + tools/hv/hv_kvp_daemon.c | 2 +- 6 files changed, 134 insertions(+), 27 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-vmbus
Signature · 1 line
2.18.0
PATCH 1/5 Tools: hv: Fix a bug in the key delete code
From: "K. Y. Srinivasan" <[email protected]>
Fix a bug in the key delete code - the num_records range from 0 to num_records-1.
--- tools/hv/hv_kvp_daemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/hv/hv_kvp_daemon.c +1 -1
@@ -286,7 +286,7 @@ static int kvp_key_delete(int pool, const __u8 *key, int key_size)* Found a match; just move the remaining * entries up. */ -if (i == num_records) { +if (i == (num_records -1 )) { kvp_file_info[pool].num_records--;kvp_update_file (pool);return 0 ;
Signature · 1 line
2.18.0
PATCH 2/5 vmbus: add driver_override support
From: Stephen Hemminger <[email protected]>
Add support for overriding the default driver for a VMBus device in the same way that it can be done for PCI devices. This patch adds the /sys/bus/vmbus/devices/.../driver_override file and the logic for matching.
This is used by driverctl tool to do driver override.
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.com%2Fdriverctl%2Fdriverctl&data=02%7C01%7Ckys%40microsoft.com%7C42e803feb2c544ef6ea908d5fd538878%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636693457619960040&sdata=kEyYHRIjNZCk%2B37moCSqbrZL426YccNQrsWpENcrZdw%3D&reserved=0
--- Documentation/ABI/testing/sysfs-bus-vmbus | 21 ++++ drivers/hv/vmbus_drv.c | 115 ++++++++++++++++++---- include/linux/hyperv.h | 1 + 3 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-vmbus
Documentation/ABI/testing/sysfs-bus-vmbus new file +21 -0
@@ -0,0 +1,21 @@ +What: /sys/bus/vmbus/devices/.../driver_override +Date: August 2019 +Contact: Stephen Hemminger <[email protected]> +Description: + This file allows the driver for a device to be specified which + will override standard static and dynamic ID matching. When + specified, only a driver with a name matching the value written + to driver_override will have an opportunity to bind to the + device. The override is specified by writing a string to the + driver_override file (echo uio_hv_generic > driver_override) and + may be cleared with an empty string (echo > driver_override). + This returns the device to standard matching rules binding. + Writing to driver_override does not automatically unbind the + device from its current driver or make any attempt to + automatically load the specified driver. If no driver with a + matching name is currently loaded in the kernel, the device + will not bind to any driver. This also allows devices to + opt-out of driver binding using a driver_override name such as + "none". Only a single driver may be specified in the override, + there is no support for parsing delimiters. +
drivers/hv/vmbus_drv.c +96 -19
164 lines not on this page · raw message
include/linux/hyperv.h +1 -0
@@ -1125,6 +1125,7 @@ struct hv_device {u16 device_id;struct device device; +char *driver_override;/* Driver name to force a match */ struct vmbus_channel *channel;struct kset *channels_kset;
Signature · 1 line
2.18.0
RE: [PATCH 2/5] vmbus: add driver_override support
From: [email protected] <[email protected]> Sent: Friday, August 10, 2018 4:06 PM
Quoted 21 lines
From: Stephen Hemminger <[email protected]>
Add support for overriding the default driver for a VMBus device in the same way that it can be done for PCI devices. This patch adds the
/sys/bus/vmbus/devices/.../driver_overridefile and the logic for matching.This is used by driverctl tool to do driver override.
https://gitlab.com/driverctl/driverctlSigned-off-by Stephen Hemminger <[email protected]>Signed-off-by K. Y. Srinivasan <[email protected]>---
drivers/hv/vmbus_drv.c +0
-0@@ -498,6 +498,54 @@ static ssize_t device_show(struct device *dev, }static DEVICE_ATTR_RO (device);
drivers/hv/vmbus_drv.c static ssize_t device_show(struct device *dev, · line 510
Quoted 10 lines
drivers/hv/vmbus_drv.c +10
-0+static ssize_t driver_override_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{ +struct hv_device *hv_dev =device_to_hv_device (dev); +char *driver_override, *old, *cp; + +/* We need to keep extra room for a newline */ +if (count >= (PAGE_SIZE -1 )) +return -EINVAL ;
Does 'count' actually have a relationship to PAGE_SIZE, or is PAGE_SIZE just used as an arbitrary size limit? I'm wondering what happens on ARM64 with a 64K page size, for example. If it's just arbitrary, coding such a constant would be better.
Quoted 4 lines
drivers/hv/vmbus_drv.c +4
-0+/* +* Return a matching hv_vmbus_device_id pointer. +* If there is no match, return NULL. +*/
drivers/hv/vmbus_drv.c static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv, · line 663
Quoted 10 lines
drivers/hv/vmbus_drv.c +8
-1+static const struct hv_vmbus_device_id *hv_vmbus_get_id (struct hv_driver *drv, +struct hv_device *dev) +{ +const uuid_le *guid = &dev->dev_type; +const struct hv_vmbus_device_id *id; -return NULL ; +/* When driver_override is set, only bind to the matching driver */ +if (dev->driver_override &&strcmp (dev->driver_override, drv->name)) +return NULL ;
This function needs to be covered by the device lock, so that dev->driver_override can't be set to NULL and the memory freed during the above 'if' statement. When called from vmbus_probe(), the device lock is held, so it's good. But when called from vmbus_match(), the device lock may not be held: consider the path __driver_attach() -> driver_match_device() -> vmbus_match().
Michael
[email protected]
maintainerRe: [PATCH 2/5] vmbus: add driver_override support
Quoted 23 lines · Michael Kelley (EOSG)
From: [email protected] <[email protected]> Sent: Friday, August 10, 2018 4:06 PM
Quoted 21 lines
From: Stephen Hemminger <[email protected]>
Add support for overriding the default driver for a VMBus device in the same way that it can be done for PCI devices. This patch adds the
/sys/bus/vmbus/devices/.../driver_overridefile and the logic for matching.This is used by driverctl tool to do driver override.
https://gitlab.com/driverctl/driverctlSigned-off-by Stephen Hemminger <[email protected]>Signed-off-by K. Y. Srinivasan <[email protected]>---
drivers/hv/vmbus_drv.c +0
-0@@ -498,6 +498,54 @@ static ssize_t device_show(struct device *dev, }static DEVICE_ATTR_RO (device);
Quoted 16 lines
drivers/hv/vmbus_drv.c static ssize_t device_show(struct device *dev, · line 510
Quoted 10 lines
drivers/hv/vmbus_drv.c +10
-0+static ssize_t driver_override_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{ +struct hv_device *hv_dev =device_to_hv_device (dev); +char *driver_override, *old, *cp; + +/* We need to keep extra room for a newline */ +if (count >= (PAGE_SIZE -1 )) +return -EINVAL ;Does 'count' actually have a relationship to
PAGE_SIZE, or isPAGE_SIZEjust used as an arbitrary size limit? I'm wondering what happens on ARM64 with a 64K page size, for example. If it's just arbitrary, coding such a constant would be better.
sysfs buffers are PAGE_SIZE big.
Re: [PATCH 2/5] vmbus: add driver_override support
In reply to Michael Kelley (EOSG)Quoted 23 lines · On Mon, 13 Aug 2018 19:30:50 +0000 "Michael Kelley (EOSG)"…
From: [email protected] <[email protected]> Sent: Friday, August 10, 2018 4:06 PM
Quoted 21 lines
From: Stephen Hemminger <[email protected]>
Add support for overriding the default driver for a VMBus device in the same way that it can be done for PCI devices. This patch adds the
/sys/bus/vmbus/devices/.../driver_overridefile and the logic for matching.This is used by driverctl tool to do driver override.
https://gitlab.com/driverctl/driverctlSigned-off-by Stephen Hemminger <[email protected]>Signed-off-by K. Y. Srinivasan <[email protected]>---
drivers/hv/vmbus_drv.c +0
-0@@ -498,6 +498,54 @@ static ssize_t device_show(struct device *dev, }static DEVICE_ATTR_RO (device);
Quoted 16 lines
drivers/hv/vmbus_drv.c static ssize_t device_show(struct device *dev, · line 510
Quoted 10 lines
drivers/hv/vmbus_drv.c +10
-0+static ssize_t driver_override_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{ +struct hv_device *hv_dev =device_to_hv_device (dev); +char *driver_override, *old, *cp; + +/* We need to keep extra room for a newline */ +if (count >= (PAGE_SIZE -1 )) +return -EINVAL ;Does 'count' actually have a relationship to
PAGE_SIZE, or isPAGE_SIZEjust used as an arbitrary size limit? I'm wondering what happens on ARM64 with a 64K page size, for example. If it's just arbitrary, coding such a constant would be better.
This comes from original code how sysfs works. Sysfs uses PAGE_SIZE for string buffers on store. This code snippet was cloned from PCI version of same thing.
Quoted 10 lines
Quoted 10 lines
drivers/hv/vmbus_drv.c +9
-0+/* +* Return a matching hv_vmbus_device_id pointer. +* If there is no match, return NULL. +*/ +static const struct hv_vmbus_device_id *hv_vmbus_get_id (struct hv_driver *drv, +struct hv_device *dev) +{ +const uuid_le *guid = &dev->dev_type; +const struct hv_vmbus_device_id *id;
Quoted 11 lines
drivers/hv/vmbus_drv.c static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv, · line 663
Quoted 4 lines
drivers/hv/vmbus_drv.c +3
-1-return NULL ; +/* When driver_override is set, only bind to the matching driver */ +if (dev->driver_override &&strcmp (dev->driver_override, drv->name)) +return NULL ;This function needs to be covered by the device lock, so that
dev->driver_overridecan't be set to NULL and the memory freed during the above 'if' statement. When called fromvmbus_probe(), the device lock is held, so it's good. But when called fromvmbus_match(), the device lock may not be held: consider the path__driver_attach()->driver_match_device()->vmbus_match().
The patch clones existing locking model from PCI.
So either both are broken, or somehow vmbus is behaving differently. I will investigate.
Re: [PATCH 2/5] vmbus: add driver_override support
In reply to Michael Kelley (EOSG)Quoted 10 lines · On Mon, 13 Aug 2018 19:30:50 +0000 "Michael Kelley (EOSG)"…
Quoted 10 lines
drivers/hv/vmbus_drv.c +9
-0+/* +* Return a matching hv_vmbus_device_id pointer. +* If there is no match, return NULL. +*/ +static const struct hv_vmbus_device_id *hv_vmbus_get_id (struct hv_driver *drv, +struct hv_device *dev) +{ +const uuid_le *guid = &dev->dev_type; +const struct hv_vmbus_device_id *id;
Quoted 11 lines
drivers/hv/vmbus_drv.c static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv, · line 663
Quoted 4 lines
drivers/hv/vmbus_drv.c +3
-1-return NULL ; +/* When driver_override is set, only bind to the matching driver */ +if (dev->driver_override &&strcmp (dev->driver_override, drv->name)) +return NULL ;This function needs to be covered by the device lock, so that
dev->driver_overridecan't be set to NULL and the memory freed during the above 'if' statement. When called fromvmbus_probe(), the device lock is held, so it's good. But when called fromvmbus_match(), the device lock may not be held: consider the path__driver_attach()->driver_match_device()->vmbus_match().
The function hv_vmbus_get_id is called from that path. i.e. __device_attach -> driver-match_device -> vmbus_match. and __device_attach always does:
device_lock(dev);
The code in driver _override_store uses the same device_lock when storing the new value.
This is same locking as is done in pci-sysfs.c
RE: [PATCH 2/5] vmbus: add driver_override support
From: Stephen Hemminger <[email protected]> Sent: Tuesday, August 14, 2018 9:35 AM
Quoted 25 lines
Quoted 10 lines · On Mon, 13 Aug 2018 19:30:50 +0000 "Michael Kelley (EOSG)"…
Quoted 10 lines
drivers/hv/vmbus_drv.c +9
-0+/* +* Return a matching hv_vmbus_device_id pointer. +* If there is no match, return NULL. +*/ +static const struct hv_vmbus_device_id *hv_vmbus_get_id (struct hv_driver *drv, +struct hv_device *dev) +{ +const uuid_le *guid = &dev->dev_type; +const struct hv_vmbus_device_id *id;Quoted 11 lines
drivers/hv/vmbus_drv.c static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv, · line 663
Quoted 4 lines
drivers/hv/vmbus_drv.c +3
-1-return NULL ; +/* When driver_override is set, only bind to the matching driver */ +if (dev->driver_override &&strcmp (dev->driver_override, drv->name)) +return NULL ;This function needs to be covered by the device lock, so that
dev->driver_overridecan't be set to NULL and the memory freed during the above 'if' statement. When called fromvmbus_probe(), the device lock is held, so it's good. But when called fromvmbus_match(), the device lock may not be held: consider the path__driver_attach()->driver_match_device()->vmbus_match().
Quoted 4 lines
The function
hv_vmbus_get_idis called from that path. i.e.__device_attach-> driver-match_device ->vmbus_match. and__device_attachalways does:device_lock(dev);
Agreed. The __device_attach() path holds the device lock and all is good. But the __driver_attach() path does not hold the device lock when the match function is called, leaving the code open to a potential race. Same problem could happen in the pci subsystem, so the issue is more generic and probably should be evaluated and dealt with separately.
Michael
Quoted 5 lines
The code in driver
_override_storeuses the samedevice_lockwhen storing the new value.This is same locking as is done in
pci-sysfs.c
PATCH 3/5 uio_hv_generic: increase size of receive and send buffers
In reply to [email protected]From: Stephen Hemminger <[email protected]>
When using DPDK there is significant performance boost by using the largest possible send and receive buffer area.
Unfortunately, with UIO model there is not a good way to configure this at run time. But it is okay to have a bigger buffer available even if application only decides to use a smaller piece of it.
--- drivers/uio/uio_hv_generic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/uio/uio_hv_generic.c +3 -3
@@ -35,13 +35,13 @@#include "../hv/hyperv_vmbus.h" -#define DRIVER_VERSION "0.02.0" +#define DRIVER_VERSION "0.02.1"#define DRIVER_AUTHOR "Stephen Hemminger <sthemmin at microsoft.com>"#define DRIVER_DESC "Generic UIO driver for VMBus devices"#define HV_RING_SIZE 512/* pages */ -#define SEND_BUFFER_SIZE (15 * 1024 * 1024) -#define RECV_BUFFER_SIZE (15 * 1024 * 1024) +#define SEND_BUFFER_SIZE (16 * 1024 * 1024) +#define RECV_BUFFER_SIZE (31 * 1024 * 1024)/* * List of resources to be mapped to user space
Signature · 1 line
2.18.0
PATCH 4/5 uio_hv_generic: drop #ifdef DEBUG
In reply to [email protected]From: Stephen Hemminger <[email protected]>
DEBUG is leftover from the development phase, remove it.
--- drivers/uio/uio_hv_generic.c | 1 - 1 file changed, 1 deletion(-)
drivers/uio/uio_hv_generic.c +0 -1
@@ -19,7 +19,6 @@* # echo -n "ed963694-e847-4b2a-85af-bc9cfc11d6f3" \ * > /sys/bus/vmbus/drivers/uio_hv_generic/bind */ -#define DEBUG 1#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt#include <linux/device.h>
Signature · 1 line
2.18.0
PATCH 5/5 Drivers: hv: vmbus: Fix synic per-cpu context initialization
In reply to [email protected]From: Michael Kelley <[email protected]>
If hv_synic_alloc() errors out, the state of the per-cpu context for some CPUs is unknown since the zero'ing is done as each CPU is iterated over. In such case, hv_synic_cleanup() may try to free memory based on uninitialized values. Fix this by zero'ing the per-cpu context for all CPUs before doing any memory allocations that might fail.
--- drivers/hv/hv.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/hv/hv.c +12 -3
@@ -189,6 +189,17 @@ static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu)int hv_synic_alloc (void ) {int cpu; +struct hv_per_cpu_context *hv_cpu; + +/* +* First, zero all per-cpu memory areas so hv_synic_free() can +* detect what memory has been allocated and cleanup properly +* after any failures. +*/ +for_each_present_cpu (cpu) { + hv_cpu =per_cpu_ptr (hv_context.cpu_context, cpu); +memset (hv_cpu,0 ,sizeof (*hv_cpu)); + } hv_context.hv_numa_map =kcalloc (nr_node_ids,sizeof (struct cpumask ),GFP_KERNEL );
@@ -198,10 +209,8 @@ int hv_synic_alloc(void) }for_each_present_cpu (cpu) { -struct hv_per_cpu_context *hv_cpu - =per_cpu_ptr (hv_context.cpu_context, cpu); + hv_cpu =per_cpu_ptr (hv_context.cpu_context, cpu); -memset (hv_cpu,0 ,sizeof (*hv_cpu));tasklet_init (&hv_cpu->msg_dpc, vmbus_on_msg_dpc, (unsigned long ) hv_cpu);
Signature · 1 line
2.18.0
RE: [PATCH 1/5] Tools: hv: Fix a bug in the key delete code
In reply to [email protected]From: [email protected] <[email protected]> Sent: Friday, August 10, 2018 4:06 PM
Quoted 8 lines
Fix a bug in the key delete code - the
num_recordsrange from 0 to num_records-1.Signed-off-by K. Y. Srinivasan <[email protected]>Reported-by David Binderman <[email protected]>Cc <[email protected]>---