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.c193
1 files changed, 188 insertions, 5 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 79b615873838..d2249f174e20 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");
@@ -488,7 +489,12 @@ static struct fuse_conn *new_conn(struct super_block *sb)
488 err = bdi_init(&fc->bdi); 489 err = bdi_init(&fc->bdi);
489 if (err) 490 if (err)
490 goto error_kfree; 491 goto error_kfree;
491 err = bdi_register_dev(&fc->bdi, fc->dev); 492 if (sb->s_bdev) {
493 err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk",
494 MAJOR(fc->dev), MINOR(fc->dev));
495 } else {
496 err = bdi_register_dev(&fc->bdi, fc->dev);
497 }
492 if (err) 498 if (err)
493 goto error_bdi_destroy; 499 goto error_bdi_destroy;
494 /* 500 /*
@@ -547,6 +553,174 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
547 return fuse_iget(sb, 1, 0, &attr, 0, 0); 553 return fuse_iget(sb, 1, 0, &attr, 0, 0);
548} 554}
549 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 fuse_conn *fc = get_fuse_conn_super(sb);
566 struct inode *inode;
567 struct dentry *entry;
568 int err = -ESTALE;
569
570 if (handle->nodeid == 0)
571 goto out_err;
572
573 inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid);
574 if (!inode) {
575 struct fuse_entry_out outarg;
576 struct qstr name;
577
578 if (!fc->export_support)
579 goto out_err;
580
581 name.len = 1;
582 name.name = ".";
583 err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg,
584 &inode);
585 if (err && err != -ENOENT)
586 goto out_err;
587 if (err || !inode) {
588 err = -ESTALE;
589 goto out_err;
590 }
591 err = -EIO;
592 if (get_node_id(inode) != handle->nodeid)
593 goto out_iput;
594 }
595 err = -ESTALE;
596 if (inode->i_generation != handle->generation)
597 goto out_iput;
598
599 entry = d_alloc_anon(inode);
600 err = -ENOMEM;
601 if (!entry)
602 goto out_iput;
603
604 if (get_node_id(inode) != FUSE_ROOT_ID) {
605 entry->d_op = &fuse_dentry_operations;
606 fuse_invalidate_entry_cache(entry);
607 }
608
609 return entry;
610
611 out_iput:
612 iput(inode);
613 out_err:
614 return ERR_PTR(err);
615}
616
617static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
618 int connectable)
619{
620 struct inode *inode = dentry->d_inode;
621 bool encode_parent = connectable && !S_ISDIR(inode->i_mode);
622 int len = encode_parent ? 6 : 3;
623 u64 nodeid;
624 u32 generation;
625
626 if (*max_len < len)
627 return 255;
628
629 nodeid = get_fuse_inode(inode)->nodeid;
630 generation = inode->i_generation;
631
632 fh[0] = (u32)(nodeid >> 32);
633 fh[1] = (u32)(nodeid & 0xffffffff);
634 fh[2] = generation;
635
636 if (encode_parent) {
637 struct inode *parent;
638
639 spin_lock(&dentry->d_lock);
640 parent = dentry->d_parent->d_inode;
641 nodeid = get_fuse_inode(parent)->nodeid;
642 generation = parent->i_generation;
643 spin_unlock(&dentry->d_lock);
644
645 fh[3] = (u32)(nodeid >> 32);
646 fh[4] = (u32)(nodeid & 0xffffffff);
647 fh[5] = generation;
648 }
649
650 *max_len = len;
651 return encode_parent ? 0x82 : 0x81;
652}
653
654static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
655 struct fid *fid, int fh_len, int fh_type)
656{
657 struct fuse_inode_handle handle;
658
659 if ((fh_type != 0x81 && fh_type != 0x82) || fh_len < 3)
660 return NULL;
661
662 handle.nodeid = (u64) fid->raw[0] << 32;
663 handle.nodeid |= (u64) fid->raw[1];
664 handle.generation = fid->raw[2];
665 return fuse_get_dentry(sb, &handle);
666}
667
668static struct dentry *fuse_fh_to_parent(struct super_block *sb,
669 struct fid *fid, int fh_len, int fh_type)
670{
671 struct fuse_inode_handle parent;
672
673 if (fh_type != 0x82 || fh_len < 6)
674 return NULL;
675
676 parent.nodeid = (u64) fid->raw[3] << 32;
677 parent.nodeid |= (u64) fid->raw[4];
678 parent.generation = fid->raw[5];
679 return fuse_get_dentry(sb, &parent);
680}
681
682static struct dentry *fuse_get_parent(struct dentry *child)
683{
684 struct inode *child_inode = child->d_inode;
685 struct fuse_conn *fc = get_fuse_conn(child_inode);
686 struct inode *inode;
687 struct dentry *parent;
688 struct fuse_entry_out outarg;
689 struct qstr name;
690 int err;
691
692 if (!fc->export_support)
693 return ERR_PTR(-ESTALE);
694
695 name.len = 2;
696 name.name = "..";
697 err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode),
698 &name, &outarg, &inode);
699 if (err && err != -ENOENT)
700 return ERR_PTR(err);
701 if (err || !inode)
702 return ERR_PTR(-ESTALE);
703
704 parent = d_alloc_anon(inode);
705 if (!parent) {
706 iput(inode);
707 return ERR_PTR(-ENOMEM);
708 }
709 if (get_node_id(inode) != FUSE_ROOT_ID) {
710 parent->d_op = &fuse_dentry_operations;
711 fuse_invalidate_entry_cache(parent);
712 }
713
714 return parent;
715}
716
717static const struct export_operations fuse_export_operations = {
718 .fh_to_dentry = fuse_fh_to_dentry,
719 .fh_to_parent = fuse_fh_to_parent,
720 .encode_fh = fuse_encode_fh,
721 .get_parent = fuse_get_parent,
722};
723
550static const struct super_operations fuse_super_operations = { 724static const struct super_operations fuse_super_operations = {
551 .alloc_inode = fuse_alloc_inode, 725 .alloc_inode = fuse_alloc_inode,
552 .destroy_inode = fuse_destroy_inode, 726 .destroy_inode = fuse_destroy_inode,
@@ -576,6 +750,13 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
576 fc->no_lock = 1; 750 fc->no_lock = 1;
577 if (arg->flags & FUSE_ATOMIC_O_TRUNC) 751 if (arg->flags & FUSE_ATOMIC_O_TRUNC)
578 fc->atomic_o_trunc = 1; 752 fc->atomic_o_trunc = 1;
753 if (arg->minor >= 9) {
754 /* LOOKUP has dependency on proto version */
755 if (arg->flags & FUSE_EXPORT_SUPPORT)
756 fc->export_support = 1;
757 }
758 if (arg->flags & FUSE_BIG_WRITES)
759 fc->big_writes = 1;
579 } else { 760 } else {
580 ra_pages = fc->max_read / PAGE_CACHE_SIZE; 761 ra_pages = fc->max_read / PAGE_CACHE_SIZE;
581 fc->no_lock = 1; 762 fc->no_lock = 1;
@@ -584,7 +765,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
584 fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); 765 fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
585 fc->minor = arg->minor; 766 fc->minor = arg->minor;
586 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; 767 fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
587 fc->max_write = min_t(unsigned, 4096, fc->max_write); 768 fc->max_write = max_t(unsigned, 4096, fc->max_write);
588 fc->conn_init = 1; 769 fc->conn_init = 1;
589 } 770 }
590 fuse_put_request(fc, req); 771 fuse_put_request(fc, req);
@@ -599,7 +780,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
599 arg->major = FUSE_KERNEL_VERSION; 780 arg->major = FUSE_KERNEL_VERSION;
600 arg->minor = FUSE_KERNEL_MINOR_VERSION; 781 arg->minor = FUSE_KERNEL_MINOR_VERSION;
601 arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; 782 arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
602 arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC; 783 arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
784 FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES;
603 req->in.h.opcode = FUSE_INIT; 785 req->in.h.opcode = FUSE_INIT;
604 req->in.numargs = 1; 786 req->in.numargs = 1;
605 req->in.args[0].size = sizeof(*arg); 787 req->in.args[0].size = sizeof(*arg);
@@ -644,6 +826,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
644 sb->s_magic = FUSE_SUPER_MAGIC; 826 sb->s_magic = FUSE_SUPER_MAGIC;
645 sb->s_op = &fuse_super_operations; 827 sb->s_op = &fuse_super_operations;
646 sb->s_maxbytes = MAX_LFS_FILESIZE; 828 sb->s_maxbytes = MAX_LFS_FILESIZE;
829 sb->s_export_op = &fuse_export_operations;
647 830
648 file = fget(d.fd); 831 file = fget(d.fd);
649 if (!file) 832 if (!file)
@@ -659,7 +842,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
659 fc->flags = d.flags; 842 fc->flags = d.flags;
660 fc->user_id = d.user_id; 843 fc->user_id = d.user_id;
661 fc->group_id = d.group_id; 844 fc->group_id = d.group_id;
662 fc->max_read = min_t(unsigned, 4096, d.max_read); 845 fc->max_read = max_t(unsigned, 4096, d.max_read);
663 846
664 /* Used by get_root_inode() */ 847 /* Used by get_root_inode() */
665 sb->s_fs_info = fc; 848 sb->s_fs_info = fc;
@@ -773,7 +956,7 @@ static inline void unregister_fuseblk(void)
773} 956}
774#endif 957#endif
775 958
776static void fuse_inode_init_once(struct kmem_cache *cachep, void *foo) 959static void fuse_inode_init_once(void *foo)
777{ 960{
778 struct inode * inode = foo; 961 struct inode * inode = foo;
779 962