Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Pavol Sakac <sakacpav@amazon.de>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"Rafael J . Wysocki" <rafael@kernel.org>,
	Danilo Krummrich <dakr@kernel.org>, Tejun Heo <tj@kernel.org>
Cc: <linux-kernel@vger.kernel.org>, <driver-core@lists.linux.dev>,
	"David Woodhouse" <dwmw@amazon.co.uk>,
	Pasha Tatashin <pasha.tatashin@soleen.com>,
	Mike Rapoport <rppt@kernel.org>,
	Pratyush Yadav <pratyush@kernel.org>,
	"David Matlack" <dmatlack@google.com>,
	Samiullah Khawaja <skhawaja@google.com>,
	Alexander Graf <graf@amazon.com>, <linux-mm@kvack.org>,
	<kexec@lists.infradead.org>, <nh-open-source@amazon.com>
Subject: [RFC PATCH 00/14] driver core: defer per-VF sysfs creation for fast SR-IOV bring-up
Date: Thu, 2 Jul 2026 19:40:19 +0200	[thread overview]
Message-ID: <20260702174033.32116-1-sakacpav@amazon.de> (raw)

Virtualization hardware keeps increasing in CPU-core and VF density.
Kernel is trending towards preserving VFs using LUO across a kexec
which will put SR-IOV in live-update hotpath. VFs must be re-added to
the sysfs tree, along with its supporting devices (e.g. vfio,
iommu_groups). On production hardware a single VF can consume ~80 kernfs
nodes. With thousands of VFs on modern hardware, hundreds of thousands
of kernfs nodes need to be created, which can add 100ms+ to the boot
time and to guest downtime.

Proposed here is a PoC of deferred materialization of sysfs files until
first access to avoid cost of kernfs node creation in hot path. In the
reproducer below using a synthetic VF to isolate the sysfs overhead,
the per-device sysfs-creation time is reduced by ~74%. It exploits the
expected access pattern of hypervisors, where only a subset of device
files need to be accessed to attach a VF to a VM on the hot path.

To allow lazy init scheme, a minimal set of files and directories is
built per device: a device directory resolves directly to the device's
kobject and is used to materialize attributes at access time. The
access is trapped in kernfs at the dir-read or path-walk stage and
depending on the trigger, either the full directory or a single file is
materialized.

The changes are two logically distinct parts:

  1. Refactor of hardcoded device_add / iommu_group sysfs attribute
     creation to a table-driven form to allow walkability of all
     attributes and single point of definition for attributes
     regardless of lazy opt-in to avoid duplicate definitions and
     associated maintainability issues with it.
  2. Lazy-init infra to front-run access to device files at lookup/
     readdir time to trigger materialization. Opt-in per device: PCI VFs
     and VFIO devices opt in via device_set_sysfs_lazy(); iommu_group
     opts in at the kobject level.

As a PoC, the code does not yet follow this logical structure in the
commit sequence and likely does not yet cover all corner cases.

Synthetic reproducer measurements
---------------------------------
  devices   per-dev time   total time       kernfs nodes (base -> lazy)
  -------   ------------   --------------   ----------------------------
     500    31.8->8.3 us    15.9-> 4.1 ms     36,417 ->  3,922  (72.8->7.8/dev)
    1000    33.2->8.7 us    33.2-> 8.7 ms     73,427 ->  8,432  (73.4->8.4/dev)
    2500    32.8->9.1 us    82.0->22.7 ms    184,421 -> 21,925  (73.8->8.8/dev)
    5000    33.0->8.7 us   165.1->43.5 ms    369,401 -> 44,406  (73.9->8.9/dev)

The reproducer is synthetic: an in-kernel module registers N unbound
platform devices (60 attributes / 4 groups, ~74 kernfs nodes each; no
config space, BARs, or probe) in one timed burst that models SR-IOV
enablement. It runs as a two-kernel A/B from one vanilla 7.1-rc2 tree
(eager baseline vs patched, plus a patched/opt-in-OFF arm), 20 runs per
point. Measures only sysfs-creation slice.

Deferral removes ~74% of the sysfs-creation time and ~88% of the kernfs
nodes. At 5000 devices that is 121.6 ms removed (165.1 -> 43.5 ms) and
~325,000 fewer kernfs nodes (369,401 -> 44,406). The table-driven rework
adds a +7..+11% eager-path time overhead to non-opted devices.

Available as a docker image that orchestrates builds in qemu guest and
prints results as a table (x86_64 Linux host with /dev/kvm assumed):

   docker run --device /dev/kvm ghcr.io/pavsa/linux-lazy-sysfs-vf-bench:7.1-rc2

Assumptions / Trade-offs
------------------------
The saving depends on the access pattern of hypervisors, and on no
component walking the whole device tree on the hot path to avoid full
materialization. Both are expected to hold on optimized hypervisors.

An actual production hypervisor was observed in local testing to
materialize an additional 5-10% of total nodes on average on the hot
path.

Overhead: +7..+11% eager-path time overhead applies to every non-opted
device going through device_add() as all struct devices traverse the
walker and can't be gated under a config option.
The lazy opt-in infra can be gated under config option to have zero
impact if disabled.

Final words
-----------
This is an RFC to first get feedback on the decisions taken at driver
core + kernfs level before engaging maintainers of other subsystems
if we want to pursue this further or pivot to something else.

The code is at a proof-of-concept quality written with AI assistance
with some known limitations with main target to gather potential
savings and initiate conversation.

Feedback appreciated for:
- table-driven attribute refactor targeting common device add path /
  suggestions for more efficient/less invasive approach
- mechanism of interception in kernfs, materialization, locking scheme
- fit into context of LUO - complementary or is there some other
  mechanism already considered to mitigate the sysfs impact

Pavol Sakac (14):
  kernfs: add populate callbacks and KERNFS_LAZY flag for lazy dir
    population
  sysfs: add existence-check helpers for lazy populate races
  sysfs: introduce sysfs_kf_syscall_ops dispatching to kobj_type
  driver core: add struct sysfs_lazy_state and device_set_sysfs_lazy()
  driver core: add struct device_sysfs_entry and walker
  driver core: wire device_ktype populate to walker
  driver core: migrate device sysfs to device_sysfs_entry table
  PCI/sysfs: migrate to device_sysfs_entry, defer physfn symlink
  iommu: lazy-populate iommu_group reserved_regions/type attrs
  PCI/IOV: opt SR-IOV VFs into sysfs_lazy
  vfio: opt vfio-dev and VFIO group devices into sysfs_lazy
  driver core: test: add KUnit tests for device_sysfs_apply
  Documentation: add lazy sysfs initialisation and device_sysfs_entry
    docs
  selftests: sysfs-lazy: add tests for lazy sysfs initialization

 Documentation/ABI/testing/sysfs-lazy          |   77 +
 Documentation/driver-api/index.rst            |    1 +
 Documentation/driver-api/sysfs-lazy.rst       |  146 ++
 MAINTAINERS                                   |    4 +
 drivers/base/bus.c                            |   41 +-
 drivers/base/core.c                           | 1047 +++++++++--
 drivers/base/test/.kunitconfig                |    7 +
 drivers/base/test/Kconfig                     |   13 +
 drivers/base/test/Makefile                    |    2 +
 drivers/base/test/device_sysfs_apply_test.c   | 1601 +++++++++++++++++
 drivers/iommu/iommu.c                         |  132 +-
 drivers/pci/iov.c                             |   24 +-
 drivers/pci/pci-sysfs.c                       |  158 +-
 drivers/pci/pci.h                             |    5 +
 drivers/pci/probe.c                           |    4 +-
 drivers/vfio/group.c                          |    5 +
 drivers/vfio/vfio_main.c                      |    5 +
 fs/kernfs/dir.c                               |   43 +-
 fs/sysfs/dir.c                                |   43 +
 fs/sysfs/file.c                               |   39 +
 fs/sysfs/group.c                              |   70 +
 fs/sysfs/mount.c                              |   60 +-
 fs/sysfs/sysfs.h                              |    7 +-
 include/linux/device.h                        |   90 +-
 include/linux/kernfs.h                        |   28 +
 include/linux/kobject.h                       |   15 +
 include/linux/sysfs.h                         |   39 +
 tools/testing/selftests/Makefile              |    1 +
 tools/testing/selftests/sysfs-lazy/.gitignore |    3 +
 tools/testing/selftests/sysfs-lazy/Makefile   |   24 +
 tools/testing/selftests/sysfs-lazy/README.rst |   52 +
 tools/testing/selftests/sysfs-lazy/config     |    6 +
 .../selftests/sysfs-lazy/iommu_groups.c       |  162 ++
 .../selftests/sysfs-lazy/kmsg_cursor.h        |  167 ++
 .../selftests/sysfs-lazy/pci_resource.c       |  284 +++
 tools/testing/selftests/sysfs-lazy/settings   |    1 +
 .../testing/selftests/sysfs-lazy/sysfs-lazy.c |  777 ++++++++
 .../selftests/sysfs-lazy/test_mod/Makefile    |   28 +
 .../sysfs-lazy/test_mod/sysfs_lazy_test_mod.c |  319 ++++
 39 files changed, 5341 insertions(+), 189 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-lazy
 create mode 100644 Documentation/driver-api/sysfs-lazy.rst
 create mode 100644 drivers/base/test/device_sysfs_apply_test.c
 create mode 100644 tools/testing/selftests/sysfs-lazy/.gitignore
 create mode 100644 tools/testing/selftests/sysfs-lazy/Makefile
 create mode 100644 tools/testing/selftests/sysfs-lazy/README.rst
 create mode 100644 tools/testing/selftests/sysfs-lazy/config
 create mode 100644 tools/testing/selftests/sysfs-lazy/iommu_groups.c
 create mode 100644 tools/testing/selftests/sysfs-lazy/kmsg_cursor.h
 create mode 100644 tools/testing/selftests/sysfs-lazy/pci_resource.c
 create mode 100644 tools/testing/selftests/sysfs-lazy/settings
 create mode 100644 tools/testing/selftests/sysfs-lazy/sysfs-lazy.c
 create mode 100644 tools/testing/selftests/sysfs-lazy/test_mod/Makefile
 create mode 100644 tools/testing/selftests/sysfs-lazy/test_mod/sysfs_lazy_test_mod.c


base-commit: ec89572766744e844df24c27d31c97b4c00f4e07
-- 
2.47.3




Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christof Hellmis, Andreas Stieger
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597



             reply	other threads:[~2026-07-03  0:48 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-02 17:40 Pavol Sakac [this message]
2026-07-02 17:40 ` [RFC PATCH 01/14] kernfs: add populate callbacks and KERNFS_LAZY flag for lazy dir population Pavol Sakac
2026-07-02 17:40 ` [RFC PATCH 02/14] sysfs: add existence-check helpers for lazy populate races Pavol Sakac
2026-07-02 17:40 ` [RFC PATCH 03/14] sysfs: introduce sysfs_kf_syscall_ops dispatching to kobj_type Pavol Sakac
2026-07-02 17:40 ` [RFC PATCH 04/14] driver core: add struct sysfs_lazy_state and device_set_sysfs_lazy() Pavol Sakac
2026-07-02 17:51 ` [RFC PATCH 05/14] driver core: add struct device_sysfs_entry and walker Pavol Sakac
2026-07-02 17:51   ` [RFC PATCH 06/14] driver core: wire device_ktype populate to walker Pavol Sakac
2026-07-02 17:51   ` [RFC PATCH 07/14] driver core: migrate device sysfs to device_sysfs_entry table Pavol Sakac
2026-07-02 17:51   ` [RFC PATCH 08/14] PCI/sysfs: migrate to device_sysfs_entry, defer physfn symlink Pavol Sakac
2026-07-02 17:51   ` [RFC PATCH 09/14] iommu: lazy-populate iommu_group reserved_regions/type attrs Pavol Sakac
2026-07-10 14:19     ` Greg Kroah-Hartman
2026-07-02 17:51   ` [RFC PATCH 10/14] PCI/IOV: opt SR-IOV VFs into sysfs_lazy Pavol Sakac
2026-07-02 17:51   ` [RFC PATCH 11/14] vfio: opt vfio-dev and VFIO group devices " Pavol Sakac
2026-07-02 17:51   ` [RFC PATCH 12/14] driver core: test: add KUnit tests for device_sysfs_apply Pavol Sakac
2026-07-02 17:51   ` [RFC PATCH 13/14] Documentation: add lazy sysfs initialisation and device_sysfs_entry docs Pavol Sakac
2026-07-02 17:51   ` [RFC PATCH 14/14] selftests: sysfs-lazy: add tests for lazy sysfs initialization Pavol Sakac
2026-07-10 14:16 ` [RFC PATCH 00/14] driver core: defer per-VF sysfs creation for fast SR-IOV bring-up Greg Kroah-Hartman

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=20260702174033.32116-1-sakacpav@amazon.de \
    --to=sakacpav@amazon.de \
    --cc=dakr@kernel.org \
    --cc=dmatlack@google.com \
    --cc=driver-core@lists.linux.dev \
    --cc=dwmw@amazon.co.uk \
    --cc=graf@amazon.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=kexec@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=nh-open-source@amazon.com \
    --cc=pasha.tatashin@soleen.com \
    --cc=pratyush@kernel.org \
    --cc=rafael@kernel.org \
    --cc=rppt@kernel.org \
    --cc=skhawaja@google.com \
    --cc=tj@kernel.org \
    /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