summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-06-07 18:53:52 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-08-28 19:15:13 -0800
commit5e39a8e3eda53b3eb964da89a0a0bba09bb6e9a9 (patch)
treedb760d19ed7de660c9468bfe69d1b3421e59dd23
parent24b3bdde02c73e29f1bc609e76f0de90494f9f7b (diff)
bcachefs: nfs export support
-rw-r--r--drivers/md/bcache/fs.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/md/bcache/fs.c b/drivers/md/bcache/fs.c
index 8bd6697d164a..3ce40da5e84e 100644
--- a/drivers/md/bcache/fs.c
+++ b/drivers/md/bcache/fs.c
@@ -17,6 +17,7 @@
#include <linux/aio.h>
#include <linux/backing-dev.h>
#include <linux/compat.h>
+#include <linux/exportfs.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/random.h>
@@ -1320,6 +1321,57 @@ static const struct super_operations bch_super_operations = {
#endif
};
+static struct inode *bch_nfs_get_inode(struct super_block *sb,
+ u64 ino, u32 generation)
+{
+ struct inode *inode;
+
+ if (ino < BCACHE_ROOT_INO)
+ return ERR_PTR(-ESTALE);
+
+ inode = bch_vfs_inode_get(sb, ino);
+ if (IS_ERR(inode))
+ return ERR_CAST(inode);
+
+ if (generation && inode->i_generation != generation) {
+ iput(inode);
+ return ERR_PTR(-ESTALE);
+ }
+ return inode;
+}
+
+static struct dentry *bch_fh_to_dentry(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ bch_nfs_get_inode);
+}
+
+static struct dentry *bch_fh_to_parent(struct super_block *sb, struct fid *fid,
+ int fh_len, int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ bch_nfs_get_inode);
+}
+
+static struct dentry *bch_get_parent(struct dentry *child)
+{
+ struct inode *dir = d_inode(child);
+ struct qstr dotdot = QSTR_INIT("..", 2);
+ u64 ino = bch_dirent_lookup(dir, &dotdot);
+
+ if (!ino)
+ return ERR_PTR(-ENOENT);
+
+ return d_obtain_alias(bch_vfs_inode_get(dir->i_sb, ino));
+}
+
+static const struct export_operations bch_export_ops = {
+ .fh_to_dentry = bch_fh_to_dentry,
+ .fh_to_parent = bch_fh_to_parent,
+ .get_parent = bch_get_parent,
+};
+
static int bch_test_super(struct super_block *s, void *data)
{
return s->s_fs_info == data;
@@ -1373,6 +1425,7 @@ static struct dentry *bch_mount(struct file_system_type *fs_type,
sb->s_blocksize_bits = PAGE_SHIFT;
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_op = &bch_super_operations;
+ sb->s_export_op = &bch_export_ops;
sb->s_xattr = bch_xattr_handlers;
sb->s_magic = BCACHE_STATFS_MAGIC;
sb->s_time_gran = 1;