[PATCH v6 1/4] fs: configfs: add helpers for opening non-configfs paths
Runyu Xiao
runyu.xiao at seu.edu.cn
Sat Sep 26 02:21:45 PDT 2026
Configfs store callbacks hold frag_sem while they run. Reopening a path
that resolves to configfs from such a callback can acquire the same
non-recursive semaphore again.
Add configfs_file_open() for configured pathnames and configfs_open_root()
for paths relative to a resolved root. Reject configfs roots before using
file_open_root() so the normal open checks remain in place.
Assisted-by: LLM Codex
Signed-off-by: Runyu Xiao <runyu.xiao at seu.edu.cn>
---
fs/configfs/mount.c | 50 ++++++++++++++++++++++++++++++++++++++++
include/linux/configfs.h | 5 ++++
2 files changed, 58 insertions(+)
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index d8cac1cbf3bd5..8d3c809676640 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/fs_context.h>
+#include <linux/namei.h>
#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -118,6 +119,58 @@ static struct file_system_type configfs_fs_type = {
};
MODULE_ALIAS_FS("configfs");
+/**
+ * configfs_open_root - open a path below a non-configfs root
+ * @root: resolved root path
+ * @name: path relative to @root
+ * @flags: open flags
+ * @mode: mode for a newly created file
+ *
+ * Use this from configfs store callbacks with a resolved non-configfs root
+ * to avoid re-entering configfs while the callback holds its fragment
+ * semaphore.
+ *
+ * Return: opened file, or an ERR_PTR() value. Returns -EINVAL if @root
+ * is on configfs.
+ */
+struct file *configfs_open_root(const struct path *root, const char *name,
+ int flags, umode_t mode)
+{
+ if (root->dentry->d_sb->s_type == &configfs_fs_type)
+ return ERR_PTR(-EINVAL);
+
+ return file_open_root(root, name, flags, mode);
+}
+EXPORT_SYMBOL_GPL(configfs_open_root);
+
+/**
+ * configfs_file_open - open an existing non-configfs pathname
+ * @filename: pathname to open; it must already exist
+ * @flags: open flags for the existing pathname
+ * @mode: unused; creation is not supported
+ *
+ * Resolve @filename and reject configfs paths. Use this from configfs
+ * store callbacks for existing configured paths.
+ *
+ * Return: opened file, or an ERR_PTR() value. Returns -EINVAL if the
+ * resolved path is on configfs.
+ */
+struct file *configfs_file_open(const char *filename, int flags, umode_t mode)
+{
+ struct file *file;
+ struct path path;
+ int ret;
+
+ ret = kern_path(filename, LOOKUP_FOLLOW, &path);
+ if (ret)
+ return ERR_PTR(ret);
+
+ file = configfs_open_root(&path, "", flags, mode);
+ path_put(&path);
+ return file;
+}
+EXPORT_SYMBOL_GPL(configfs_file_open);
+
struct dentry *configfs_pin_fs(void)
{
int err = simple_pin_fs(&configfs_fs_type, &configfs_mount,
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index ef65c75beeaad..2a803bb836b4d 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -34,6 +34,8 @@ struct configfs_group_operations;
struct configfs_attribute;
struct configfs_bin_attribute;
struct configfs_subsystem;
+struct file;
+struct path;
struct config_item {
char *ci_name;
@@ -243,6 +245,9 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
int configfs_register_group(struct config_group *parent_group,
struct config_group *group);
void configfs_unregister_group(struct config_group *group);
+struct file *configfs_open_root(const struct path *root, const char *name,
+ int flags, umode_t mode);
+struct file *configfs_file_open(const char *filename, int flags, umode_t mode);
void configfs_remove_default_groups(struct config_group *group);
--
2.34.1
More information about the Linux-nvme
mailing list