From: "Darrick J. Wong" <djwong@kernel.org>
To: brauner@kernel.org
Cc: linux-ext4@vger.kernel.org, linux-xfs@vger.kernel.org,
hch@lst.de, linux-fsdevel@vger.kernel.org
Subject: [PATCH V4.1 1/4] fs: send uevents for filesystem mount events
Date: Thu, 18 Dec 2025 15:33:24 -0800 [thread overview]
Message-ID: <20251218233324.GQ94594@frogsfrogsfrogs> (raw)
In-Reply-To: <176602332527.688213.9644123318095990966.stgit@frogsfrogsfrogs>
From: Darrick J. Wong <djwong@kernel.org>
Add the ability to send uevents whenever a filesystem mounts, unmounts,
or goes down. This will enable XFS to start daemons whenever a
filesystem is first mounted.
Regrettably, we can't wire this directly into get_tree_bdev_flags or
generic_shutdown_super because not all filesystems set up a kobject
representation in sysfs, and the VFS has no idea if a filesystem
actually does that.
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
v4.1: replace open-coded buffer formatting with seqbuf
---
include/linux/fsevent.h | 33 ++++++++++++
fs/Makefile | 2 -
fs/fsevent.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 160 insertions(+), 1 deletion(-)
create mode 100644 include/linux/fsevent.h
create mode 100644 fs/fsevent.c
diff --git a/include/linux/fsevent.h b/include/linux/fsevent.h
new file mode 100644
index 00000000000000..548e35861e545f
--- /dev/null
+++ b/include/linux/fsevent.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2025 Oracle. All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef _LINUX_FSEVENT_H__
+#define _LINUX_FSEVENT_H__
+
+void fsevent_send_mount(struct super_block *sb, struct kobject *kobject,
+ struct fs_context *fc);
+
+void fsevent_send(struct super_block *sb, struct kobject *kobject,
+ enum kobject_action kaction);
+
+static inline void fsevent_send_unmount(struct super_block *sb,
+ struct kobject *kobject)
+{
+ fsevent_send(sb, kobject, KOBJ_REMOVE);
+}
+
+static inline void fsevent_send_remount(struct super_block *sb,
+ struct kobject *kobject)
+{
+ fsevent_send(sb, kobject, KOBJ_CHANGE);
+}
+
+static inline void fsevent_send_shutdown(struct super_block *sb,
+ struct kobject *kobject)
+{
+ fsevent_send(sb, kobject, KOBJ_OFFLINE);
+}
+
+#endif /* _LINUX_FSEVENT_H__ */
diff --git a/fs/Makefile b/fs/Makefile
index b4d182465405fe..266981bd25ab09 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -158,7 +158,7 @@ obj-y := open.o read_write.o file_table.o super.o \
stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
fs_dirent.o fs_context.o fs_parser.o fsopen.o init.o \
kernel_read_file.o mnt_idmapping.o remap_range.o pidfs.o \
- file_attr.o fserror.o
+ file_attr.o fserror.o fsevent.o
obj-$(CONFIG_BUFFER_HEAD) += buffer.o mpage.o
obj-$(CONFIG_PROC_FS) += proc_namespace.o
diff --git a/fs/fsevent.c b/fs/fsevent.c
new file mode 100644
index 00000000000000..d37f42f844e057
--- /dev/null
+++ b/fs/fsevent.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2025 Oracle. All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#include <linux/fs.h>
+#include <linux/kobject.h>
+#include <linux/fs_context.h>
+#include <linux/seq_buf.h>
+#include <linux/fsevent.h>
+
+static inline size_t fs_uevent_bufsize(const struct super_block *sb,
+ const char *source,
+ unsigned int *envlen)
+{
+ size_t ret = sizeof("TYPE=filesystem") +
+ sizeof("SID=") + sizeof_field(struct super_block, s_id);
+ *envlen += 2;
+
+ if (source) {
+ ret += sizeof("SOURCE=") + strlen(source) + 1;
+ (*envlen)++;
+ }
+
+ if (sb->s_uuid_len == sizeof(sb->s_uuid)) {
+ ret += sizeof("UUID=") + UUID_STRING_LEN;
+ (*envlen)++;
+ }
+
+ /* null array element terminator */
+ ret++;
+ (*envlen)++;
+ return ret;
+}
+
+static char **format_uevent_strings(struct super_block *sb, const char *source)
+{
+ struct seq_buf sbuf;
+ unsigned int envlen = 0;
+ size_t buflen = fs_uevent_bufsize(sb, source, &envlen);
+ char *buf;
+ char **env, **envp;
+
+ buf = kzalloc(buflen, GFP_KERNEL);
+ if (!buf)
+ return NULL;
+ env = kcalloc(envlen, sizeof(char *), GFP_KERNEL);
+ if (!env) {
+ kfree(buf);
+ return NULL;
+ }
+
+ seq_buf_init(&sbuf, buf, buflen);
+ envp = env;
+
+ /*
+ * Add a second null terminator on the end so the next printf can start
+ * printing at the second null terminator.
+ */
+ seq_buf_get_buf(&sbuf, envp++);
+ seq_buf_printf(&sbuf, "TYPE=filesystem");
+ seq_buf_putc(&sbuf, 0);
+
+ seq_buf_get_buf(&sbuf, envp++);
+ seq_buf_printf(&sbuf, "SID=%s", sb->s_id);
+ seq_buf_putc(&sbuf, 0);
+
+ if (source) {
+ seq_buf_get_buf(&sbuf, envp++);
+ seq_buf_printf(&sbuf, "SOURCE=%s", source);
+ seq_buf_putc(&sbuf, 0);
+ }
+
+ if (sb->s_uuid_len == sizeof(sb->s_uuid)) {
+ seq_buf_get_buf(&sbuf, envp++);
+ seq_buf_printf(&sbuf, "UUID=%pU", &sb->s_uuid);
+ seq_buf_putc(&sbuf, 0);
+ }
+
+ /* Add null terminator to strings array */
+ *envp = NULL;
+
+ if (seq_buf_has_overflowed(&sbuf)) {
+ WARN_ON(1);
+ kfree(env);
+ kfree(buf);
+ return NULL;
+ }
+
+ return env;
+}
+
+static inline void free_uevent_strings(char **env)
+{
+ kfree(env[0]);
+ kfree(env);
+}
+
+/*
+ * Send a uevent signalling that the mount succeeded so we can use udev rules
+ * to start background services.
+ */
+void fsevent_send_mount(struct super_block *sb, struct kobject *kobject,
+ struct fs_context *fc)
+{
+ char **env = format_uevent_strings(sb, fc->source);
+
+ if (env) {
+ kobject_uevent_env(kobject, KOBJ_ADD, env);
+ free_uevent_strings(env);
+ }
+}
+EXPORT_SYMBOL_GPL(fsevent_send_mount);
+
+/* Send a uevent signalling that something happened to a live mount. */
+void fsevent_send(struct super_block *sb, struct kobject *kobject,
+ enum kobject_action kaction)
+{
+ char **env = format_uevent_strings(sb, NULL);
+
+ if (env) {
+ kobject_uevent_env(kobject, kaction, env);
+ free_uevent_strings(env);
+ }
+}
+EXPORT_SYMBOL_GPL(fsevent_send);
next prev parent reply other threads:[~2025-12-18 23:33 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-18 2:02 [PATCHSET V4 2/2] fs: send uevents on mount and unmount Darrick J. Wong
2025-12-18 2:04 ` [PATCH 1/4] fs: send uevents for filesystem mount events Darrick J. Wong
2025-12-18 5:26 ` Christoph Hellwig
2025-12-18 19:49 ` Darrick J. Wong
2025-12-18 23:33 ` Darrick J. Wong [this message]
2025-12-24 12:47 ` Christian Brauner
2025-12-26 23:58 ` Ian Kent
2026-01-05 17:26 ` Darrick J. Wong
2026-01-05 17:25 ` Darrick J. Wong
2025-12-18 2:04 ` [PATCH 2/4] xfs: send uevents when major filesystem events happen Darrick J. Wong
2025-12-18 5:27 ` Christoph Hellwig
2025-12-18 2:05 ` [PATCH 3/4] ext4: convert ext4_root to a kset Darrick J. Wong
2025-12-18 5:27 ` Christoph Hellwig
2025-12-18 2:05 ` [PATCH 4/4] ext4: send uevents when major filesystem events happen Darrick J. Wong
2025-12-18 5:27 ` Christoph Hellwig
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=20251218233324.GQ94594@frogsfrogsfrogs \
--to=djwong@kernel.org \
--cc=brauner@kernel.org \
--cc=hch@lst.de \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-xfs@vger.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