aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 3141690558c8..71fa76a48a31 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -18,6 +18,7 @@
18#include <linux/statfs.h> 18#include <linux/statfs.h>
19#include <linux/random.h> 19#include <linux/random.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21#include <linux/exportfs.h>
21 22
22MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); 23MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
23MODULE_DESCRIPTION("Filesystem in Userspace"); 24MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -552,6 +553,119 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
552 return fuse_iget(sb, 1, 0, &attr, 0, 0); 553 return fuse_iget(sb, 1, 0, &attr, 0, 0);
553} 554}
554 555
556struct fuse_inode_handle
557{
558 u64 nodeid;
559 u32 generation;
560};
561
562static struct dentry *fuse_get_dentry(struct super_block *sb,
563 struct fuse_inode_handle *handle)
564{
565 struct inode *inode;
566 struct dentry *entry;
567 int err = -ESTALE;
568
569 if (handle->nodeid == 0)
570 goto out_err;
571
572 inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid);
573 if (!inode)
574 goto out_err;
575 err = -ESTALE;
576 if (inode->i_generation != handle->generation)
577 goto out_iput;
578
579 entry = d_alloc_anon(inode);
580 err = -ENOMEM;
581 if (!entry)
582 goto out_iput;
583
584 if (get_node_id(inode) != FUSE_ROOT_ID) {
585 entry->d_op = &fuse_dentry_operations;
586 fuse_invalidate_entry_cache(entry);
587 }
588
589 return entry;
590
591 out_iput:
592 iput(inode);
593 out_err:
594 return ERR_PTR(err);
595}
596
597static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
598 int connectable)
599{
600 struct inode *inode = dentry->d_inode;
601 bool encode_parent = connectable && !S_ISDIR(inode->i_mode);
602 int len = encode_parent ? 6 : 3;
603 u64 nodeid;
604 u32 generation;
605
606 if (*max_len < len)
607 return 255;
608
609 nodeid = get_fuse_inode(inode)->nodeid;
610 generation = inode->i_generation;
611
612 fh[0] = (u32)(nodeid >> 32);
613 fh[1] = (u32)(nodeid & 0xffffffff);
614 fh[2] = generation;
615
616 if (encode_parent) {
617 struct inode *parent;
618
619 spin_lock(&dentry->d_lock);
620 parent = dentry->d_parent->d_inode;
621 nodeid = get_fuse_inode(parent)->nodeid;
622 generation = parent->i_generation;
623 spin_unlock(&dentry->d_lock);
624
625 fh[3] = (u32)(nodeid >> 32);
626 fh[4] = (u32)(nodeid & 0xffffffff);
627 fh[5] = generation;
628 }
629
630 *max_len = len;
631 return encode_parent ? 0x82 : 0x81;
632}
633
634static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
635 struct fid *fid, int fh_len, int fh_type)
636{
637 struct fuse_inode_handle handle;
638
639 if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3)
640 return NULL;
641
642 handle.nodeid = (u64) fid->raw[0] << 32;
643 handle.nodeid |= (u64) fid->raw[1];
644 handle.generation = fid->raw[2];
645 return fuse_get_dentry(sb, &handle);
646}
647
648static struct dentry *fuse_fh_to_parent(struct super_block *sb,
649 struct fid *fid, int fh_len, int fh_type)
650{
651 struct fuse_inode_handle parent;
652
653 if (fh_type != 0x82 || fh_len < 6)
654 return NULL;
655
656 parent.nodeid = (u64) fid->raw[3] << 32;
657 parent.nodeid |= (u64) fid->raw[4];
658 parent.generation = fid->raw[5];
659 return fuse_get_dentry(sb, &parent);
660}
661
662
663static const struct export_operations fuse_export_operations = {
664 .fh_to_dentry = fuse_fh_to_dentry,
665 .fh_to_parent = fuse_fh_to_parent,
666 .encode_fh = fuse_encode_fh,
667};
668
555static const struct super_operations fuse_super_operations = { 669static const struct super_operations fuse_super_operations = {
556 .alloc_inode = fuse_alloc_inode, 670 .alloc_inode = fuse_alloc_inode,
557 .destroy_inode = fuse_destroy_inode, 671 .destroy_inode = fuse_destroy_inode,
@@ -652,6 +766,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
652 sb->s_magic = FUSE_SUPER_MAGIC; 766 sb->s_magic = FUSE_SUPER_MAGIC;
653 sb->s_op = &fuse_super_operations; 767 sb->s_op = &fuse_super_operations;
654 sb->s_maxbytes = MAX_LFS_FILESIZE; 768 sb->s_maxbytes = MAX_LFS_FILESIZE;
769 sb->s_export_op = &fuse_export_operations;
655 770
656 file = fget(d.fd); 771 file = fget(d.fd);
657 if (!file) 772 if (!file)