From: Hannes Reinecke <hare@kernel.org>
To: Christian Brauner <brauner@kernel.org>
Cc: Jan Kara <jack@suse.cz>, Andreas Hindborg <a.hindborg@kernel.org>,
linux-fsdevel@vger.kernel.org, linux-nvme@lists.infradead.org,
Hannes Reinecke <hare@kernel.org>
Subject: [PATCH 6/8] fs/configfs: add 'fill_subsystem' and 'clear_subsystem' callbacks
Date: Sat, 13 Jun 2026 13:14:35 +0200 [thread overview]
Message-ID: <20260613111437.101763-7-hare@kernel.org> (raw)
In-Reply-To: <20260613111437.101763-1-hare@kernel.org>
When creating a new per-namespace filesystem static initialisation
doesn't work, so implement a 'fill_subsystem' and 'clear_subsystem'
callbacks to 'struct configfs_subsystem' to allow for every driver
to populate the subsystem structure dynamicall.
Signed-off-by: Hannes Reinecke <hare@kernel.org>
---
fs/configfs/configfs_internal.h | 4 ++
fs/configfs/dir.c | 90 ++++++++++++++++++++++++++++++++-
fs/configfs/mount.c | 6 +++
include/linux/configfs.h | 5 ++
4 files changed, 103 insertions(+), 2 deletions(-)
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h
index a91e97194c3d..7992a7da3de6 100644
--- a/fs/configfs/configfs_internal.h
+++ b/fs/configfs/configfs_internal.h
@@ -94,6 +94,10 @@ extern struct dentry *configfs_pin_fs(struct super_block *sb);
extern void configfs_release_fs(struct super_block *sb);
extern struct configfs_super_info *configfs_get_super_info(u64 ns_id);
extern void configfs_put_super_info(struct configfs_super_info *info);
+extern void configfs_link_subsystems(struct super_block *sb,
+ struct configfs_super_info *info);
+extern void configfs_unlink_subsystems(struct super_block *sb,
+ struct configfs_super_info *info);
extern const struct file_operations configfs_dir_operations;
extern const struct file_operations configfs_file_operations;
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 6e111e3fd0e0..bf59165acec7 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1902,15 +1902,81 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
goto out_put;
}
+ if (subsys->fill_subsystem) {
+ err = subsys->fill_subsystem(subsys, info->ns_id);
+ if (err)
+ goto out_release;
+ }
+
err = configfs_link_root(info, subsys, root);
+ if (err) {
+ subsys->clear_subsystem(subsys, info->ns_id);
+ goto out_put;
+ }
+
+ mutex_lock(&info->subsys_mutex);
+ list_add(&subsys->su_link, &info->subsys_list);
+ mutex_unlock(&info->subsys_mutex);
+
+out_release:
if (err)
configfs_release_fs(NULL);
-
out_put:
configfs_put_super_info(info);
return err;
}
+void configfs_link_subsystems(struct super_block *sb,
+ struct configfs_super_info *info)
+{
+ struct configfs_subsystem *s;
+ struct configfs_super_info *parent = configfs_get_super_info(0);
+
+ if (WARN_ON(IS_ERR(parent)))
+ return;
+ if (WARN_ON(parent == info))
+ return;
+ mutex_lock(&parent->subsys_mutex);
+ list_for_each_entry(s, &parent->subsys_list, su_link) {
+ struct configfs_subsystem *subsys;
+ struct dentry *root;
+ int err;
+
+ if (!s->fill_subsystem)
+ continue;
+ subsys = kzalloc_obj(*subsys);
+ if (!subsys)
+ continue;
+ subsys->fill_subsystem = s->fill_subsystem;
+ subsys->clear_subsystem = s->clear_subsystem;
+ INIT_LIST_HEAD(&subsys->su_link);
+ mutex_init(&subsys->su_mutex);
+ err = subsys->fill_subsystem(subsys, info->ns_id);
+ if (err) {
+ kfree(subsys);
+ continue;
+ }
+ root = configfs_pin_fs(sb);
+ if (IS_ERR(root)) {
+ subsys->clear_subsystem(subsys, info->ns_id);
+ kfree(subsys);
+ continue;
+ }
+ err = configfs_link_root(info, subsys, root);
+ if (err) {
+ configfs_release_fs(sb);
+ subsys->clear_subsystem(subsys, info->ns_id);
+ kfree(subsys);
+ continue;
+ }
+ mutex_lock(&info->subsys_mutex);
+ list_add(&subsys->su_link, &info->subsys_list);
+ mutex_unlock(&info->subsys_mutex);
+ }
+ mutex_unlock(&parent->subsys_mutex);
+ configfs_put_super_info(parent);
+}
+
static void configfs_unlink_root(struct configfs_subsystem *subsys)
{
struct config_group *group = &subsys->su_group;
@@ -1952,6 +2018,24 @@ static void configfs_unlink_root(struct configfs_subsystem *subsys)
dput(dentry);
}
+void configfs_unlink_subsystems(struct super_block *sb,
+ struct configfs_super_info *info)
+{
+ struct configfs_subsystem *subsys, *s;
+
+ mutex_lock(&info->subsys_mutex);
+ list_for_each_entry_safe(subsys, s, &info->subsys_list, su_link) {
+ list_del_init(&subsys->su_link);
+ configfs_unlink_root(subsys);
+ if (subsys->clear_subsystem)
+ subsys->clear_subsystem(subsys, info->ns_id);
+ unlink_group(&subsys->su_group);
+ configfs_release_fs(sb);
+ kfree(subsys);
+ }
+ mutex_unlock(&info->subsys_mutex);
+}
+
void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
{
struct configfs_super_info *info = configfs_get_super_info(0);
@@ -1959,9 +2043,11 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys)
if (WARN_ON(IS_ERR(info)))
return;
-
mutex_lock(&info->subsys_mutex);
+ list_del_init(&subsys->su_link);
configfs_unlink_root(subsys);
+ if (subsys->clear_subsystem)
+ subsys->clear_subsystem(subsys, info->ns_id);
unlink_group(group);
mutex_unlock(&info->subsys_mutex);
configfs_release_fs(NULL);
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index 8cf4bda14bec..8de3ae0cb6dd 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -142,6 +142,10 @@ static int configfs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_fs_info = info;
set_default_d_op(sb, &configfs_dentry_ops); /* the rest get that */
sb->s_d_flags |= DCACHE_DONTCACHE;
+
+ pr_info("%s: ns %llu\n", __func__, info->ns_id);
+ configfs_link_subsystems(sb, info);
+
return 0;
}
@@ -164,6 +168,8 @@ static void configfs_kill_sb(struct super_block *sb)
{
struct configfs_super_info *info = sb->s_fs_info;
+ pr_info("%s: ns %llu\n", __func__, info->ns_id);
+ configfs_unlink_subsystems(sb, info);
kill_anon_super(sb);
configfs_put_super_info(info);
sb->s_fs_info = NULL;
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index ef65c75beeaa..ce88da5bdcec 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -226,8 +226,13 @@ struct configfs_group_operations {
};
struct configfs_subsystem {
+ struct list_head su_link;
struct config_group su_group;
struct mutex su_mutex;
+ int (*fill_subsystem)(struct configfs_subsystem *subsys,
+ u64 ns_id);
+ void (*clear_subsystem)(struct configfs_subsystem *subsys,
+ u64 ns_id);
};
static inline struct configfs_subsystem *to_configfs_subsystem(struct config_group *group)
--
2.51.0
next prev parent reply other threads:[~2026-06-13 11:15 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-13 11:14 [RFC PATCH 0/8] namespace-aware configfs Hannes Reinecke
2026-06-13 11:14 ` [PATCH 1/8] fs/configfs: rework configfs_is_root() Hannes Reinecke
2026-06-13 11:14 ` [PATCH 2/8] fs/configfs: dynamically allocate super_info Hannes Reinecke
2026-06-13 11:14 ` [PATCH 3/8] fs/configfs: separate out configfs_{link,unlink}_root() Hannes Reinecke
2026-06-13 11:14 ` [PATCH 4/8] fs/namespace: implement mnt_clone_direct() Hannes Reinecke
2026-06-13 11:14 ` [PATCH 5/8] fs/configfs: add superblock as attribute to configfs_pin_fs() Hannes Reinecke
2026-06-13 11:14 ` Hannes Reinecke [this message]
2026-06-13 11:14 ` [PATCH 7/8] fs/configfs: switch to get_tree_keyed() Hannes Reinecke
2026-06-13 11:14 ` [PATCH 8/8] nvmet: make configfs setup namespace aware Hannes Reinecke
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=20260613111437.101763-7-hare@kernel.org \
--to=hare@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=brauner@kernel.org \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-nvme@lists.infradead.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 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.