summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorShaohua Li <shli@fb.com>2017-07-12 14:49:51 -0400
committerJens Axboe <axboe@kernel.dk>2017-07-29 11:00:03 -0400
commitaa8188253474b4053bc2900d9fcb545ce68bdf5c (patch)
tree7d7afd563e9f2cd46cf8c0a0299aab42fcf764e9 /fs
parentc53cd490b1a491ebf1d8e30da97e7231459a4208 (diff)
kernfs: add exportfs operations
Now we have the facilities to implement exportfs operations. The idea is cgroup can export the fhandle info to userspace, then userspace uses fhandle to find the cgroup name. Another example is userspace can get fhandle for a cgroup and BPF uses the fhandle to filter info for the cgroup. Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Shaohua Li <shli@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs')
-rw-r--r--fs/kernfs/mount.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c
index acd542625fd8..fa323589704f 100644
--- a/fs/kernfs/mount.c
+++ b/fs/kernfs/mount.c
@@ -16,6 +16,7 @@
16#include <linux/pagemap.h> 16#include <linux/pagemap.h>
17#include <linux/namei.h> 17#include <linux/namei.h>
18#include <linux/seq_file.h> 18#include <linux/seq_file.h>
19#include <linux/exportfs.h>
19 20
20#include "kernfs-internal.h" 21#include "kernfs-internal.h"
21 22
@@ -64,6 +65,59 @@ const struct super_operations kernfs_sops = {
64 .show_path = kernfs_sop_show_path, 65 .show_path = kernfs_sop_show_path,
65}; 66};
66 67
68static struct inode *kernfs_fh_get_inode(struct super_block *sb,
69 u64 ino, u32 generation)
70{
71 struct kernfs_super_info *info = kernfs_info(sb);
72 struct inode *inode;
73 struct kernfs_node *kn;
74
75 if (ino == 0)
76 return ERR_PTR(-ESTALE);
77
78 kn = kernfs_find_and_get_node_by_ino(info->root, ino);
79 if (!kn)
80 return ERR_PTR(-ESTALE);
81 inode = kernfs_get_inode(sb, kn);
82 kernfs_put(kn);
83 if (IS_ERR(inode))
84 return ERR_CAST(inode);
85
86 if (generation && inode->i_generation != generation) {
87 /* we didn't find the right inode.. */
88 iput(inode);
89 return ERR_PTR(-ESTALE);
90 }
91 return inode;
92}
93
94static struct dentry *kernfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
95 int fh_len, int fh_type)
96{
97 return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
98 kernfs_fh_get_inode);
99}
100
101static struct dentry *kernfs_fh_to_parent(struct super_block *sb, struct fid *fid,
102 int fh_len, int fh_type)
103{
104 return generic_fh_to_parent(sb, fid, fh_len, fh_type,
105 kernfs_fh_get_inode);
106}
107
108static struct dentry *kernfs_get_parent_dentry(struct dentry *child)
109{
110 struct kernfs_node *kn = kernfs_dentry_node(child);
111
112 return d_obtain_alias(kernfs_get_inode(child->d_sb, kn->parent));
113}
114
115static const struct export_operations kernfs_export_ops = {
116 .fh_to_dentry = kernfs_fh_to_dentry,
117 .fh_to_parent = kernfs_fh_to_parent,
118 .get_parent = kernfs_get_parent_dentry,
119};
120
67/** 121/**
68 * kernfs_root_from_sb - determine kernfs_root associated with a super_block 122 * kernfs_root_from_sb - determine kernfs_root associated with a super_block
69 * @sb: the super_block in question 123 * @sb: the super_block in question
@@ -159,6 +213,8 @@ static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
159 sb->s_magic = magic; 213 sb->s_magic = magic;
160 sb->s_op = &kernfs_sops; 214 sb->s_op = &kernfs_sops;
161 sb->s_xattr = kernfs_xattr_handlers; 215 sb->s_xattr = kernfs_xattr_handlers;
216 if (info->root->flags & KERNFS_ROOT_SUPPORT_EXPORTOP)
217 sb->s_export_op = &kernfs_export_ops;
162 sb->s_time_gran = 1; 218 sb->s_time_gran = 1;
163 219
164 /* get root inode, initialize and unlock it */ 220 /* get root inode, initialize and unlock it */