public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: David Matlack <dmatlack@google.com>
To: Raghavendra Rao Ananta <rananta@google.com>
Cc: Alex Williamson <alex@shazbot.org>,
	Alex Williamson <alex.williamson@redhat.com>,
	Josh Hilke <jrhilke@google.com>,
	kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 2/6] vfio: selftests: Introduce a sysfs lib
Date: Wed, 7 Jan 2026 22:41:16 +0000	[thread overview]
Message-ID: <aV7hDIe3tvehETXS@google.com> (raw)
In-Reply-To: <20251210181417.3677674-3-rananta@google.com>

On 2025-12-10 06:14 PM, Raghavendra Rao Ananta wrote:
> Introduce a sysfs liibrary to handle the common reads/writes to the
                    library

> PCI sysfs files, for example, getting the total number of VFs supported
> by the device via /sys/bus/pci/devices/$BDF/sriov_totalvfs. The library
> will be used in the upcoming test patch to configure the VFs for a given
> PF device.
> 
> Opportunistically, move vfio_pci_get_group_from_dev() to this library as
> it falls under the same bucket. Rename it to sysfs_get_device_group() to
> align with other function names.
> 
> Signed-off-by: Raghavendra Rao Ananta <rananta@google.com>
> ---
>  .../selftests/vfio/lib/include/libvfio.h      |   1 +
>  .../vfio/lib/include/libvfio/sysfs.h          |  16 ++
>  tools/testing/selftests/vfio/lib/libvfio.mk   |   1 +
>  tools/testing/selftests/vfio/lib/sysfs.c      | 151 ++++++++++++++++++
>  .../selftests/vfio/lib/vfio_pci_device.c      |  22 +--
>  5 files changed, 170 insertions(+), 21 deletions(-)
>  create mode 100644 tools/testing/selftests/vfio/lib/include/libvfio/sysfs.h
>  create mode 100644 tools/testing/selftests/vfio/lib/sysfs.c
> 
> diff --git a/tools/testing/selftests/vfio/lib/include/libvfio.h b/tools/testing/selftests/vfio/lib/include/libvfio.h
> index 279ddcd701944..bbe1d7616a648 100644
> --- a/tools/testing/selftests/vfio/lib/include/libvfio.h
> +++ b/tools/testing/selftests/vfio/lib/include/libvfio.h
> @@ -5,6 +5,7 @@
>  #include <libvfio/assert.h>
>  #include <libvfio/iommu.h>
>  #include <libvfio/iova_allocator.h>
> +#include <libvfio/sysfs.h>
>  #include <libvfio/vfio_pci_device.h>
>  #include <libvfio/vfio_pci_driver.h>
>  
> diff --git a/tools/testing/selftests/vfio/lib/include/libvfio/sysfs.h b/tools/testing/selftests/vfio/lib/include/libvfio/sysfs.h
> new file mode 100644
> index 0000000000000..1eca6b5cbcfcc
> --- /dev/null
> +++ b/tools/testing/selftests/vfio/lib/include/libvfio/sysfs.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +#ifndef SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_SYSFS_H
> +#define SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_SYSFS_H
> +
> +int sysfs_get_sriov_totalvfs(const char *bdf);
> +int sysfs_get_sriov_numvfs(const char *bdf);
> +void sysfs_set_sriov_numvfs(const char *bdfs, int numvfs);
> +void sysfs_get_sriov_vf_bdf(const char *pf_bdf, int i, char *out_vf_bdf);
> +bool sysfs_get_sriov_drivers_autoprobe(const char *bdf);
> +void sysfs_set_sriov_drivers_autoprobe(const char *bdf, bool val);
> +void sysfs_bind_driver(const char *bdf, const char *driver);
> +void sysfs_unbind_driver(const char *bdf, const char *driver);
> +int sysfs_get_driver(const char *bdf, char *out_driver);
> +unsigned int sysfs_get_device_group(const char *bdf);
> +
> +#endif /* SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_SYSFS_H */
> diff --git a/tools/testing/selftests/vfio/lib/libvfio.mk b/tools/testing/selftests/vfio/lib/libvfio.mk
> index 9f47bceed16f4..b7857319c3f1f 100644
> --- a/tools/testing/selftests/vfio/lib/libvfio.mk
> +++ b/tools/testing/selftests/vfio/lib/libvfio.mk
> @@ -6,6 +6,7 @@ LIBVFIO_SRCDIR := $(selfdir)/vfio/lib
>  LIBVFIO_C := iommu.c
>  LIBVFIO_C += iova_allocator.c
>  LIBVFIO_C += libvfio.c
> +LIBVFIO_C += sysfs.c
>  LIBVFIO_C += vfio_pci_device.c
>  LIBVFIO_C += vfio_pci_driver.c
>  
> diff --git a/tools/testing/selftests/vfio/lib/sysfs.c b/tools/testing/selftests/vfio/lib/sysfs.c
> new file mode 100644
> index 0000000000000..5551e8b981075
> --- /dev/null
> +++ b/tools/testing/selftests/vfio/lib/sysfs.c
> @@ -0,0 +1,151 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <linux/limits.h>
> +
> +#include <libvfio.h>
> +
> +static int sysfs_get_val(const char *component, const char *name,

nit: I'm partial to putting the verbs at the end of function names for
library calls.

e.g.

  vfio_pci_config_read()
  vfio_pci_config_write()
  vfio_pci_msi_enable()
  vfio_pci_msi_disable()

So these would be:

  sysfs_val_set()
  sysfs_val_get()
  sysfs_device_val_set()
  sysfs_device_val_get()
  sysfs_sriov_numvfs_set()
  sysfs_sriov_numvfs_get()
  ...

> +			 const char *file)
> +{
> +	char path[PATH_MAX] = {0};
> +	char buf[32] = {0};

nit: You don't need to zero-initialize these since you only use them
after they are intitialized below.

> +	int fd;
> +
> +	snprintf(path, PATH_MAX, "/sys/bus/pci/%s/%s/%s", component, name, file);

Use the new snprintf_assert() :)

> +	fd = open(path, O_RDONLY);
> +	if (fd < 0)
> +		return fd;
> +
> +	VFIO_ASSERT_GT(read(fd, buf, ARRAY_SIZE(buf)), 0);
> +	VFIO_ASSERT_EQ(close(fd), 0);
> +
> +	return strtol(buf, NULL, 0);
> +}
> +
> +static void sysfs_set_val(const char *component, const char *name,
> +			  const char *file, const char *val)
> +{
> +	char path[PATH_MAX] = {0};

Ditto here about zero-intialization being unnecessary.

> +	int fd;
> +
> +	snprintf(path, PATH_MAX, "/sys/bus/pci/%s/%s/%s", component, name, file);

Ditto here about snprintf_assert()

You get the idea... I won't comment on the ones below.

> +	VFIO_ASSERT_GT(fd = open(path, O_WRONLY), 0);
> +
> +	VFIO_ASSERT_EQ(write(fd, val, strlen(val)), strlen(val));
> +	VFIO_ASSERT_EQ(close(fd), 0);
> +}
> +
> +static int sysfs_get_device_val(const char *bdf, const char *file)
> +{
> +	sysfs_get_val("devices", bdf, file);
> +}
> +
> +static void sysfs_set_device_val(const char *bdf, const char *file, const char *val)
> +{
> +	sysfs_set_val("devices", bdf, file, val);
> +}
> +
> +static void sysfs_set_driver_val(const char *driver, const char *file, const char *val)
> +{
> +	sysfs_set_val("drivers", driver, file, val);
> +}
> +
> +static void sysfs_set_device_val_int(const char *bdf, const char *file, int val)
> +{
> +	char val_str[32] = {0};
> +
> +	snprintf(val_str, sizeof(val_str), "%d", val);
> +	sysfs_set_device_val(bdf, file, val_str);
> +}
> +
> +int sysfs_get_sriov_totalvfs(const char *bdf)
> +{
> +	return sysfs_get_device_val(bdf, "sriov_totalvfs");
> +}
> +
> +int sysfs_get_sriov_numvfs(const char *bdf)
> +{
> +	return sysfs_get_device_val(bdf, "sriov_numvfs");
> +}
> +
> +void sysfs_set_sriov_numvfs(const char *bdf, int numvfs)
> +{
> +	sysfs_set_device_val_int(bdf, "sriov_numvfs", numvfs);
> +}
> +
> +bool sysfs_get_sriov_drivers_autoprobe(const char *bdf)
> +{
> +	return (bool)sysfs_get_device_val(bdf, "sriov_drivers_autoprobe");
> +}
> +
> +void sysfs_set_sriov_drivers_autoprobe(const char *bdf, bool val)
> +{
> +	sysfs_set_device_val_int(bdf, "sriov_drivers_autoprobe", val);
> +}
> +
> +void sysfs_bind_driver(const char *bdf, const char *driver)
> +{
> +	sysfs_set_driver_val(driver, "bind", bdf);
> +}
> +
> +void sysfs_unbind_driver(const char *bdf, const char *driver)
> +{
> +	sysfs_set_driver_val(driver, "unbind", bdf);
> +}
> +
> +void sysfs_get_sriov_vf_bdf(const char *pf_bdf, int i, char *out_vf_bdf)
> +{
> +	char vf_path[PATH_MAX] = {0};
> +	char path[PATH_MAX] = {0};
> +	int ret;
> +
> +	snprintf(path, PATH_MAX, "/sys/bus/pci/devices/%s/virtfn%d", pf_bdf, i);
> +
> +	ret = readlink(path, vf_path, PATH_MAX);
> +	VFIO_ASSERT_NE(ret, -1);
> +
> +	ret = sscanf(basename(vf_path), "%s", out_vf_bdf);
> +	VFIO_ASSERT_EQ(ret, 1);
> +}
> +
> +unsigned int sysfs_get_device_group(const char *bdf)

nit: s/device_group/iommu_group/

> +{
> +	char dev_iommu_group_path[PATH_MAX] = {0};
> +	char path[PATH_MAX] = {0};
> +	unsigned int group;
> +	int ret;
> +
> +	snprintf(path, PATH_MAX, "/sys/bus/pci/devices/%s/iommu_group", bdf);
> +
> +	ret = readlink(path, dev_iommu_group_path, sizeof(dev_iommu_group_path));
> +	VFIO_ASSERT_NE(ret, -1, "Failed to get the IOMMU group for device: %s\n", bdf);
> +
> +	ret = sscanf(basename(dev_iommu_group_path), "%u", &group);
> +	VFIO_ASSERT_EQ(ret, 1, "Failed to get the IOMMU group for device: %s\n", bdf);
> +
> +	return group;
> +}
> +
> +int sysfs_get_driver(const char *bdf, char *out_driver)
> +{
> +	char driver_path[PATH_MAX] = {0};
> +	char path[PATH_MAX] = {0};
> +	int ret;
> +
> +	snprintf(path, PATH_MAX, "/sys/bus/pci/devices/%s/driver", bdf);
> +	ret = readlink(path, driver_path, PATH_MAX);
> +	if (ret == -1) {
> +		if (errno == ENOENT)
> +			return -1;
> +
> +		VFIO_FAIL("Failed to read %s\n", path);
> +	}
> +
> +	ret = sscanf(basename(driver_path), "%s", out_driver);

I think this is equivalent to:

  out_driver = basename(driver_path);

... which means out_driver to point within driver_path, which is stack
allocated? I think you want to do strcpy() after basename() to copy the
driver name to out_driver.

Also how do you prevent overflowing out_driver? Maybe it would be
cleaner for sysfs_get_driver() to allocate out_driver and return it to
the caller?

We can return an empty string for the ENOENT case.

> +	VFIO_ASSERT_EQ(ret, 1);
> +
> +	return 0;
> +}
> diff --git a/tools/testing/selftests/vfio/lib/vfio_pci_device.c b/tools/testing/selftests/vfio/lib/vfio_pci_device.c
> index 64a19481b734f..9b2a123cee5fc 100644
> --- a/tools/testing/selftests/vfio/lib/vfio_pci_device.c
> +++ b/tools/testing/selftests/vfio/lib/vfio_pci_device.c
> @@ -22,8 +22,6 @@
>  #include "../../../kselftest.h"
>  #include <libvfio.h>
>  
> -#define PCI_SYSFS_PATH	"/sys/bus/pci/devices"
> -
>  static void vfio_pci_irq_set(struct vfio_pci_device *device,
>  			     u32 index, u32 vector, u32 count, int *fds)
>  {
> @@ -181,24 +179,6 @@ void vfio_pci_device_reset(struct vfio_pci_device *device)
>  	ioctl_assert(device->fd, VFIO_DEVICE_RESET, NULL);
>  }
>  
> -static unsigned int vfio_pci_get_group_from_dev(const char *bdf)
> -{
> -	char dev_iommu_group_path[PATH_MAX] = {0};
> -	char sysfs_path[PATH_MAX] = {0};
> -	unsigned int group;
> -	int ret;
> -
> -	snprintf_assert(sysfs_path, PATH_MAX, "%s/%s/iommu_group", PCI_SYSFS_PATH, bdf);
> -
> -	ret = readlink(sysfs_path, dev_iommu_group_path, sizeof(dev_iommu_group_path));
> -	VFIO_ASSERT_NE(ret, -1, "Failed to get the IOMMU group for device: %s\n", bdf);
> -
> -	ret = sscanf(basename(dev_iommu_group_path), "%u", &group);
> -	VFIO_ASSERT_EQ(ret, 1, "Failed to get the IOMMU group for device: %s\n", bdf);
> -
> -	return group;
> -}
> -
>  static void vfio_pci_group_setup(struct vfio_pci_device *device, const char *bdf)
>  {
>  	struct vfio_group_status group_status = {
> @@ -207,7 +187,7 @@ static void vfio_pci_group_setup(struct vfio_pci_device *device, const char *bdf
>  	char group_path[32];
>  	int group;
>  
> -	group = vfio_pci_get_group_from_dev(bdf);
> +	group = sysfs_get_device_group(bdf);
>  	snprintf_assert(group_path, sizeof(group_path), "/dev/vfio/%d", group);
>  
>  	device->group_fd = open(group_path, O_RDWR);
> -- 
> 2.52.0.239.gd5f0c6e74e-goog
> 

  parent reply	other threads:[~2026-01-07 22:41 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-10 18:14 [PATCH v2 0/6] vfio: selftest: Add SR-IOV UAPI test Raghavendra Rao Ananta
2025-12-10 18:14 ` [PATCH v2 1/6] vfio: selftests: Introduce snprintf_assert() Raghavendra Rao Ananta
2026-01-07 22:21   ` David Matlack
2025-12-10 18:14 ` [PATCH v2 2/6] vfio: selftests: Introduce a sysfs lib Raghavendra Rao Ananta
2025-12-12 18:27   ` Raghavendra Rao Ananta
2025-12-18 21:52     ` David Matlack
2026-01-07 22:41   ` David Matlack [this message]
2026-01-08 21:25     ` Raghavendra Rao Ananta
2025-12-10 18:14 ` [PATCH v2 3/6] vfio: selftests: Extend container/iommufd setup for passing vf_token Raghavendra Rao Ananta
2026-01-07 22:49   ` David Matlack
2026-01-08 21:34     ` Raghavendra Rao Ananta
2025-12-10 18:14 ` [PATCH v2 4/6] vfio: selftests: Export more vfio_pci functions Raghavendra Rao Ananta
2026-01-07 22:55   ` David Matlack
2026-01-07 23:05   ` David Matlack
2026-01-08 21:47     ` Raghavendra Rao Ananta
2025-12-10 18:14 ` [PATCH v2 5/6] vfio: selftests: Add helper to set/override a vf_token Raghavendra Rao Ananta
2026-01-07 22:56   ` David Matlack
2026-01-08 21:45     ` Raghavendra Rao Ananta
2026-01-14 17:12       ` David Matlack
2025-12-10 18:14 ` [PATCH v2 6/6] vfio: selftests: Add tests to validate SR-IOV UAPI Raghavendra Rao Ananta
2025-12-12 18:21   ` Raghavendra Rao Ananta
2025-12-18 23:26   ` David Matlack
2026-01-06 19:47     ` Raghavendra Rao Ananta
2026-02-05 21:51       ` David Matlack
2026-02-23 18:57         ` David Matlack
2026-01-07 23:22   ` David Matlack
2026-01-09 19:05     ` Raghavendra Rao Ananta
2026-01-14 17:09       ` David Matlack

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aV7hDIe3tvehETXS@google.com \
    --to=dmatlack@google.com \
    --cc=alex.williamson@redhat.com \
    --cc=alex@shazbot.org \
    --cc=jrhilke@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rananta@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox