new primitive: debugfs_create_automount()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 25 Jan 2015 20:10:32 +0000 (15:10 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 25 Jan 2015 21:52:53 +0000 (16:52 -0500)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/debugfs/inode.c
include/linux/debugfs.h

index 1219dff8e18f11347b05762b0ebb2a07f8c8a693..957c40ce09f62d02a3a4039f5a5dd91ff30c5345 100644 (file)
@@ -175,6 +175,18 @@ static const struct super_operations debugfs_super_operations = {
        .show_options   = debugfs_show_options,
 };
 
+static struct vfsmount *debugfs_automount(struct path *path)
+{
+       struct vfsmount *(*f)(void *);
+       f = (struct vfsmount *(*)(void *))path->dentry->d_fsdata;
+       return f(path->dentry->d_inode->i_private);
+}
+
+static const struct dentry_operations debugfs_dops = {
+       .d_delete = always_delete_dentry,
+       .d_automount = debugfs_automount,
+};
+
 static int debug_fill_super(struct super_block *sb, void *data, int silent)
 {
        static struct tree_descr debug_files[] = {{""}};
@@ -199,6 +211,7 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent)
                goto fail;
 
        sb->s_op = &debugfs_super_operations;
+       sb->s_d_op = &debugfs_dops;
 
        debugfs_apply_options(sb);
 
@@ -367,6 +380,41 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
 }
 EXPORT_SYMBOL_GPL(debugfs_create_dir);
 
+/**
+ * debugfs_create_automount - create automount point in the debugfs filesystem
+ * @name: a pointer to a string containing the name of the file to create.
+ * @parent: a pointer to the parent dentry for this file.  This should be a
+ *          directory dentry if set.  If this parameter is NULL, then the
+ *          file will be created in the root of the debugfs filesystem.
+ * @f: function to be called when pathname resolution steps on that one.
+ * @data: opaque argument to pass to f().
+ *
+ * @f should return what ->d_automount() would.
+ */
+struct dentry *debugfs_create_automount(const char *name,
+                                       struct dentry *parent,
+                                       struct vfsmount *(*f)(void *),
+                                       void *data)
+{
+       struct dentry *dentry = start_creating(name, parent);
+       struct inode *inode;
+
+       if (IS_ERR(dentry))
+               return NULL;
+
+       inode = debugfs_get_inode(dentry->d_sb);
+       if (unlikely(!inode))
+               return failed_creating(dentry);
+
+       inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
+       inode->i_flags |= S_AUTOMOUNT;
+       inode->i_private = data;
+       dentry->d_fsdata = (void *)f;
+       d_instantiate(dentry, inode);
+       return end_creating(dentry);
+}
+EXPORT_SYMBOL(debugfs_create_automount);
+
 /**
  * debugfs_create_symlink- create a symbolic link in the debugfs filesystem
  * @name: a pointer to a string containing the name of the symbolic link to
index da4c4983adbe950c94ab8e1538a00a1ec72cabc0..ea149a24a1f20008eb0d6709beebad4971e5cef4 100644 (file)
@@ -56,6 +56,11 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
 struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
                                      const char *dest);
 
+struct dentry *debugfs_create_automount(const char *name,
+                                       struct dentry *parent,
+                                       struct vfsmount *(*f)(void *),
+                                       void *data);
+
 void debugfs_remove(struct dentry *dentry);
 void debugfs_remove_recursive(struct dentry *dentry);