From: Gabriel Krisman Bertazi <krisman@suse.de>
To: linux-fsdevel@vger.kernel.org
Cc: Gabriel Krisman Bertazi <krisman@suse.de>,
Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>,
"Theodore Ts'o" <tytso@mit.edu>, Hugh Dickins <hughd@google.com>,
Daniel Tang <danielzgtg.opensource@gmail.com>,
linux-ext4@vger.kernel.org, Miklos Szeredi <miklos@szeredi.hu>,
Amir Goldstein <amir73il@gmail.com>,
linux-unionfs@vger.kernel.org, linux-mm@kvack.org
Subject: [PATCH 3/4] ovl: Add /sys/fs/overlay plumbing
Date: Mon, 28 Sep 2026 17:31:54 -0400 [thread overview]
Message-ID: <20260928213155.2612039-4-krisman@suse.de> (raw)
In-Reply-To: <20260928213155.2612039-1-krisman@suse.de>
In preparation to expose encoding settings in sysfs, add a subtree for
overlayfs under /sys/fs. The only remarkable detail is how we reference
the volume. Use major:minor, which is not very human-friendly but it is
at least discoverable. I considered uuid, but that would be a problem
if mounted with uuid=off.
Assisted-by: LLM
Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
---
Documentation/ABI/testing/sysfs-fs-overlay | 6 ++
MAINTAINERS | 1 +
fs/overlayfs/Makefile | 2 +-
fs/overlayfs/overlayfs.h | 5 +
fs/overlayfs/ovl_entry.h | 7 ++
fs/overlayfs/super.c | 26 +++++-
fs/overlayfs/sysfs.c | 101 +++++++++++++++++++++
7 files changed, 144 insertions(+), 4 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-fs-overlay
create mode 100644 fs/overlayfs/sysfs.c
diff --git a/Documentation/ABI/testing/sysfs-fs-overlay b/Documentation/ABI/testing/sysfs-fs-overlay
new file mode 100644
index 000000000000..9060c39679ae
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-fs-overlay
@@ -0,0 +1,6 @@
+What: /sys/fs/overlay/<volume>/
+Date: September 2026
+Contact: linux-unionfs@vger.kernel.org
+Description:
+ A directory is created for every mounted overlayfs instance.
+ <volume> is set to the device major:minor.
diff --git a/MAINTAINERS b/MAINTAINERS
index c2414447892c..e49f84c4c691 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -20586,6 +20586,7 @@ M: Amir Goldstein <amir73il@gmail.com>
L: linux-unionfs@vger.kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs.git
+F: Documentation/ABI/testing/sysfs-fs-overlay
F: Documentation/filesystems/overlayfs.rst
F: fs/overlayfs/
diff --git a/fs/overlayfs/Makefile b/fs/overlayfs/Makefile
index 5648954f8588..fd4e747820c2 100644
--- a/fs/overlayfs/Makefile
+++ b/fs/overlayfs/Makefile
@@ -6,4 +6,4 @@
obj-$(CONFIG_OVERLAY_FS) += overlay.o
overlay-objs := super.o namei.o util.o inode.o file.o dir.o readdir.o \
- copy_up.o export.o params.o xattrs.o
+ copy_up.o export.o params.o xattrs.o sysfs.o
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index e0d8c6152e9f..91d3894d9bd2 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -939,6 +939,11 @@ extern const struct export_operations ovl_export_fid_operations;
/* super.c */
int ovl_fill_super(struct super_block *sb, struct fs_context *fc);
+int __init ovl_sysfs_init(void);
+void ovl_sysfs_exit(void);
+int ovl_sysfs_register(struct ovl_fs *ofs);
+void ovl_sysfs_unregister(struct ovl_fs *ofs);
+
/* Will this overlay be forced to mount/remount ro? */
static inline bool ovl_force_readonly(struct ovl_fs *ofs)
{
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index 80cad4ea96a3..c14253e75826 100644
--- a/fs/overlayfs/ovl_entry.h
+++ b/fs/overlayfs/ovl_entry.h
@@ -5,6 +5,9 @@
* Copyright (C) 2016 Red Hat, Inc.
*/
+#include <linux/completion.h>
+#include <linux/kobject.h>
+
struct ovl_config {
char *upperdir;
char *workdir;
@@ -56,6 +59,7 @@ struct ovl_entry {
/* private information held for overlayfs's superblock */
struct ovl_fs {
+ struct super_block *sb;
unsigned int numlayer;
/* Number of unique fs among layers including upper fs */
unsigned int numfs;
@@ -92,6 +96,9 @@ struct ovl_fs {
/* r/o snapshot of upperdir sb's only taken on volatile mounts */
errseq_t errseq;
bool casefold;
+ struct kobject kobj;
+ struct completion kobj_unregister;
+ bool kobj_registered;
};
/* Number of lower layers, not including data-only layers */
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index bd0a3f9039d2..d195dace135d 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -226,8 +226,10 @@ static void ovl_put_super(struct super_block *sb)
{
struct ovl_fs *ofs = OVL_FS(sb);
- if (ofs)
+ if (ofs) {
+ ovl_sysfs_unregister(ofs);
ovl_free_fs(ofs);
+ }
}
/* Sync real dirty inodes in upper filesystem (if it exists) */
@@ -1548,6 +1550,7 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
if (fc->user_ns != current_user_ns())
goto out_err;
+ ofs->sb = sb;
ovl_set_d_op(sb);
if (!ofs->creator_cred) {
@@ -1559,6 +1562,13 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
with_ovl_creds(sb)
err = ovl_fill_super_creds(fc, sb);
+ if (err)
+ goto out_err;
+ /*
+ * ->s_root is now set (by ovl_fill_super_creds), so if
+ * ovl_sysfs_register fails it will be cleaned by ovl_put_super.
+ */
+ return ovl_sysfs_register(ofs);
out_err:
if (err) {
@@ -1598,10 +1608,19 @@ static int __init ovl_init(void)
if (ovl_inode_cachep == NULL)
return -ENOMEM;
+ err = ovl_sysfs_init();
+ if (err)
+ goto out_destroy_cache;
+
err = register_filesystem(&ovl_fs_type);
- if (!err)
- return 0;
+ if (err)
+ goto out_sysfs_exit;
+
+ return 0;
+out_sysfs_exit:
+ ovl_sysfs_exit();
+out_destroy_cache:
kmem_cache_destroy(ovl_inode_cachep);
return err;
@@ -1610,6 +1629,7 @@ static int __init ovl_init(void)
static void __exit ovl_exit(void)
{
unregister_filesystem(&ovl_fs_type);
+ ovl_sysfs_exit();
/*
* Make sure all delayed rcu free inodes are flushed before we
diff --git a/fs/overlayfs/sysfs.c b/fs/overlayfs/sysfs.c
new file mode 100644
index 000000000000..be83b57f637c
--- /dev/null
+++ b/fs/overlayfs/sysfs.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Sysfs interface for overlayfs.
+ */
+#include <linux/fs.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/unicode.h>
+#include <linux/xattr.h>
+#include "overlayfs.h"
+
+static struct kset *ovl_kset;
+
+struct ovl_sysfs_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct ovl_fs *ofs, char *buf);
+};
+
+#define OVL_SYSFS_ATTR_RO(_name) \
+ static struct ovl_sysfs_attr ovl_sysfs_attr_##_name = { \
+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
+ .show = ovl_##_name##_show, \
+ }
+
+static struct attribute *ovl_sysfs_attrs[] = {
+ NULL,
+};
+ATTRIBUTE_GROUPS(ovl_sysfs);
+
+static ssize_t ovl_sysfs_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct ovl_fs *ofs = container_of(kobj, struct ovl_fs, kobj);
+ struct ovl_sysfs_attr *a = container_of(attr, struct ovl_sysfs_attr,
+ attr);
+
+ return a->show(ofs, buf);
+}
+
+static const struct sysfs_ops ovl_sysfs_ops = {
+ .show = ovl_sysfs_show,
+};
+
+static void ovl_sysfs_release(struct kobject *kobj)
+{
+ struct ovl_fs *ofs = container_of(kobj, struct ovl_fs, kobj);
+
+ complete(&ofs->kobj_unregister);
+}
+
+static const struct kobj_type ovl_sysfs_ktype = {
+ .default_groups = ovl_sysfs_groups,
+ .sysfs_ops = &ovl_sysfs_ops,
+ .release = ovl_sysfs_release,
+};
+
+int ovl_sysfs_register(struct ovl_fs *ofs)
+{
+ struct super_block *sb = ofs->sb;
+ int err;
+
+ init_completion(&ofs->kobj_unregister);
+ ofs->kobj.kset = ovl_kset;
+ err = kobject_init_and_add(&ofs->kobj, &ovl_sysfs_ktype, NULL, "%u:%u",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev));
+ if (err) {
+ kobject_put(&ofs->kobj);
+ wait_for_completion(&ofs->kobj_unregister);
+ pr_warn("failed to create sysfs volume %u:%u (err=%d).\n",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev), err);
+ return err;
+ }
+
+ ofs->kobj_registered = true;
+ kobject_uevent(&ofs->kobj, KOBJ_ADD);
+ return 0;
+}
+
+void ovl_sysfs_unregister(struct ovl_fs *ofs)
+{
+ if (!ofs->kobj_registered)
+ return;
+
+ ofs->kobj_registered = false;
+ kobject_del(&ofs->kobj);
+ kobject_put(&ofs->kobj);
+ wait_for_completion(&ofs->kobj_unregister);
+}
+
+int __init ovl_sysfs_init(void)
+{
+ ovl_kset = kset_create_and_add("overlay", NULL, fs_kobj);
+ if (!ovl_kset)
+ return -ENOMEM;
+ return 0;
+}
+
+void ovl_sysfs_exit(void)
+{
+ kset_unregister(ovl_kset);
+}
--
2.55.0
next prev parent reply other threads:[~2026-09-28 21:32 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 21:31 [PATCH 0/4] Expose encoding information of volumes Gabriel Krisman Bertazi
2026-09-28 21:31 ` [PATCH 1/4] shmem: Report casefold setting in mount options Gabriel Krisman Bertazi
2026-09-28 21:39 ` sashiko-bot
2026-09-29 14:00 ` Mohammed EL Kadiri
2026-09-29 15:17 ` Gabriel Krisman Bertazi
2026-09-28 21:31 ` [PATCH 2/4] ext4: Expose the filesystem encoding through sysfs Gabriel Krisman Bertazi
2026-09-28 21:45 ` sashiko-bot
2026-09-29 0:18 ` Gabriel Krisman Bertazi
2026-09-28 21:31 ` Gabriel Krisman Bertazi [this message]
2026-09-28 21:38 ` [PATCH 3/4] ovl: Add /sys/fs/overlay plumbing sashiko-bot
2026-09-28 21:31 ` [PATCH 4/4] ovl: Expose the filesystem encoding through sysfs Gabriel Krisman Bertazi
2026-09-28 21:37 ` sashiko-bot
2026-09-29 14:15 ` Amir Goldstein
2026-09-29 14:40 ` Pali Rohár
2026-09-29 15:35 ` Gabriel Krisman Bertazi
2026-09-29 15:35 ` Gabriel Krisman Bertazi
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=20260928213155.2612039-4-krisman@suse.de \
--to=krisman@suse.de \
--cc=amir73il@gmail.com \
--cc=brauner@kernel.org \
--cc=danielzgtg.opensource@gmail.com \
--cc=hughd@google.com \
--cc=jack@suse.cz \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-unionfs@vger.kernel.org \
--cc=miklos@szeredi.hu \
--cc=tytso@mit.edu \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.