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 04/14] driver core: add struct sysfs_lazy_state and device_set_sysfs_lazy()
Date: Thu, 2 Jul 2026 19:40:23 +0200	[thread overview]
Message-ID: <20260702174033.32116-5-sakacpav@amazon.de> (raw)
In-Reply-To: <20260702174033.32116-1-sakacpav@amazon.de>

Add the per-device lazy-sysfs bookkeeping struct and accessors that
subsystems use to opt their devices into lazy population:

  - struct sysfs_lazy_state { mutex lock; bool populated;
    bool power_added; } in include/linux/device.h.
  - dev->sysfs_lazy pointer field on struct device. Non-NULL is the
    opt-in signal device_add() consults to mark the kobj's kernfs
    directory KERNFS_LAZY.
  - Public accessors device_is_sysfs_lazy(), device_sysfs_populated(),
    device_sysfs_set_populated().
    device_sysfs_populated() uses smp_load_acquire() to pair with
    device_sysfs_set_populated()'s smp_store_release(); this lets
    the lockless fast-path in device_ktype_populate_all() (added in
    the next commit) skip the mutex while still observing all
    kernfs_create_*() side-effects performed by populate_all under
    @lock. The canonical write is under @lock.
  - device_set_sysfs_lazy() allocates the bookkeeping; idempotent and
    must be called BEFORE device_add(). Freed by device_release().

device_add() consults dev->sysfs_lazy after kobject_add(); if set,
kernfs_set_lazy(dev->kobj.sd) gates kernfs lookups and readdirs to
device_ktype.populate / populate_all.  No driver-core attribute
content is yet routed through the walker - that lands in the next
commit.  No existing caller opts in here; the plumbing is in place
for subsystems that follow in this series.

The "blob whose pointer doubles as the opt-in signal" pattern
mirrors dev_iommu_get() in drivers/iommu/iommu.c.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Rafael J. Wysocki <rafael@kernel.org>
Cc: Tejun Heo <tj@kernel.org>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: linux-kernel@vger.kernel.org
Cc: driver-core@lists.linux.dev
Cc: linux-api@vger.kernel.org
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Pavol Sakac <sakacpav@amazon.de>
---
 drivers/base/core.c    | 74 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/device.h | 28 ++++++++++++++++
 2 files changed, 102 insertions(+)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index bd2ddf2aab505..6d0d917d4b1ff 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2555,6 +2555,10 @@ static void device_release(struct kobject *kobj)
 	 */
 	devres_release_all(dev);
 
+	if (dev->sysfs_lazy)
+		mutex_destroy(&dev->sysfs_lazy->lock);
+	kfree(dev->sysfs_lazy);
+
 	kfree(dev->dma_range_map);
 	kfree(dev->driver_override.name);
 
@@ -2588,6 +2592,67 @@ static void device_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t
 		dev->class->get_ownership(dev, uid, gid);
 }
 
+/*
+ * True once populate_all has completed; lockless.  False for non-lazy.
+ *
+ * Memory-ordering: pairs with device_sysfs_set_populated()'s
+ * smp_store_release().  smp_load_acquire ensures any kernfs_create_*()
+ * side-effects performed by populate_all under sysfs_lazy.lock become
+ * visible to readers that observe @populated == true.  The kernfs
+ * lookup path also takes kernfs_rwsem(read) which provides an
+ * independent memory-barrier; the explicit acquire here is belt-and-
+ * braces for callers that may bypass kernfs (e.g. internal sysfs_*
+ * helpers and the KUnit suite).
+ */
+bool device_sysfs_populated(const struct device *dev)
+{
+	return dev->sysfs_lazy &&
+	       smp_load_acquire(&dev->sysfs_lazy->populated);
+}
+
+/*
+ * Latch @dev as fully populated. Caller holds @dev->sysfs_lazy->lock.
+ *
+ * Memory-ordering: smp_store_release() publishes all kernfs_create_*()
+ * side-effects performed under sysfs_lazy.lock to lockless readers
+ * via device_sysfs_populated()'s smp_load_acquire().
+ */
+void device_sysfs_set_populated(struct device *dev)
+{
+	smp_store_release(&dev->sysfs_lazy->populated, true);
+}
+
+/**
+ * device_set_sysfs_lazy - opt @dev into lazy sysfs (call before device_add())
+ * @dev: device to opt in
+ *
+ * Allocates @dev->sysfs_lazy.  Idempotent: a second call on a
+ * device that already opted in is a no-op.  Must be called before
+ * device_add().  After device_add() returns, eager attribute creation
+ * is skipped and walker dispatch lazily materializes attributes on
+ * first sysfs lookup or readdir.
+ *
+ * Return:
+ * * %0       - on success (or if already opted in).
+ * * %-ENOMEM - allocation failure.
+ */
+int device_set_sysfs_lazy(struct device *dev)
+{
+	struct sysfs_lazy_state *lazy;
+
+	if (dev->sysfs_lazy)
+		return 0;
+
+	lazy = kzalloc_obj(*lazy);
+	if (!lazy)
+		return -ENOMEM;
+
+	mutex_init(&lazy->lock);
+	dev->sysfs_lazy = lazy;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(device_set_sysfs_lazy);
+
 static const struct kobj_type device_ktype = {
 	.release	= device_release,
 	.sysfs_ops	= &dev_sysfs_ops,
@@ -3642,6 +3707,15 @@ int device_add(struct device *dev)
 	error = device_add_class_symlinks(dev);
 	if (error)
 		goto SymlinkError;
+	/*
+	 * device_set_sysfs_lazy() only allocates ->sysfs_lazy_state for
+	 * non-namespaced devices, and device_is_sysfs_lazy() guards opt-in
+	 * here, so kernfs_set_lazy() should always succeed.  WARN_ON catches
+	 * a regression in those preconditions.
+	 */
+	if (device_is_sysfs_lazy(dev))
+		WARN_ON(kernfs_set_lazy(dev->kobj.sd));
+
 	error = device_add_attrs(dev);
 	if (error)
 		goto AttrsError;
diff --git a/include/linux/device.h b/include/linux/device.h
index 9c8fde6a3d866..39e08e8c950c6 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -45,6 +45,18 @@ struct fwnode_handle;
 struct iommu_group;
 struct dev_pin_info;
 struct dev_iommu;
+/**
+ * struct sysfs_lazy_state - per-device lazy sysfs population state
+ * @lock: serialises populate callbacks (held across device_sysfs_apply())
+ * @populated: full-populate latch
+ * @power_added: dpm_sysfs_add() latch
+ */
+struct sysfs_lazy_state {
+	struct mutex	lock;
+	bool		populated;
+	bool		power_added;
+};
+
 struct msi_device_data;
 
 /**
@@ -739,9 +751,25 @@ struct device {
 	bool			dma_iommu:1;
 #endif
 
+	/* Lazy-sysfs opt-in (NULL = eager). Set via device_set_sysfs_lazy(). */
+	struct sysfs_lazy_state	*sysfs_lazy;
+
 	DECLARE_BITMAP(flags, DEV_FLAG_COUNT);
 };
 
+/**
+ * device_is_sysfs_lazy - true if @dev opted into lazy sysfs
+ * @dev: device to query
+ */
+static inline bool device_is_sysfs_lazy(const struct device *dev)
+{
+	return !!dev->sysfs_lazy;
+}
+
+bool device_sysfs_populated(const struct device *dev);
+void device_sysfs_set_populated(struct device *dev);
+int device_set_sysfs_lazy(struct device *dev);
+
 #define __create_dev_flag_accessors(accessor_name, flag_name) \
 static inline bool dev_##accessor_name(const struct device *dev) \
 { \
-- 
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



  parent 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 [RFC PATCH 00/14] driver core: defer per-VF sysfs creation for fast SR-IOV bring-up Pavol Sakac
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 ` Pavol Sakac [this message]
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-5-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