diff options
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r-- | fs/fuse/dir.c | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index a058b664859c..8c5d156284a0 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -705,10 +705,12 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, | |||
705 | stat->blksize = (1 << inode->i_blkbits); | 705 | stat->blksize = (1 << inode->i_blkbits); |
706 | } | 706 | } |
707 | 707 | ||
708 | static int fuse_do_getattr(struct inode *inode, struct kstat *stat) | 708 | static int fuse_do_getattr(struct inode *inode, struct kstat *stat, |
709 | struct file *file) | ||
709 | { | 710 | { |
710 | int err; | 711 | int err; |
711 | struct fuse_attr_out arg; | 712 | struct fuse_getattr_in inarg; |
713 | struct fuse_attr_out outarg; | ||
712 | struct fuse_conn *fc = get_fuse_conn(inode); | 714 | struct fuse_conn *fc = get_fuse_conn(inode); |
713 | struct fuse_req *req; | 715 | struct fuse_req *req; |
714 | u64 attr_version; | 716 | u64 attr_version; |
@@ -721,24 +723,35 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat) | |||
721 | attr_version = fc->attr_version; | 723 | attr_version = fc->attr_version; |
722 | spin_unlock(&fc->lock); | 724 | spin_unlock(&fc->lock); |
723 | 725 | ||
726 | memset(&inarg, 0, sizeof(inarg)); | ||
727 | /* Directories have separate file-handle space */ | ||
728 | if (file && S_ISREG(inode->i_mode)) { | ||
729 | struct fuse_file *ff = file->private_data; | ||
730 | |||
731 | inarg.getattr_flags |= FUSE_GETATTR_FH; | ||
732 | inarg.fh = ff->fh; | ||
733 | } | ||
724 | req->in.h.opcode = FUSE_GETATTR; | 734 | req->in.h.opcode = FUSE_GETATTR; |
725 | req->in.h.nodeid = get_node_id(inode); | 735 | req->in.h.nodeid = get_node_id(inode); |
736 | req->in.numargs = 1; | ||
737 | req->in.args[0].size = sizeof(inarg); | ||
738 | req->in.args[0].value = &inarg; | ||
726 | req->out.numargs = 1; | 739 | req->out.numargs = 1; |
727 | req->out.args[0].size = sizeof(arg); | 740 | req->out.args[0].size = sizeof(outarg); |
728 | req->out.args[0].value = &arg; | 741 | req->out.args[0].value = &outarg; |
729 | request_send(fc, req); | 742 | request_send(fc, req); |
730 | err = req->out.h.error; | 743 | err = req->out.h.error; |
731 | fuse_put_request(fc, req); | 744 | fuse_put_request(fc, req); |
732 | if (!err) { | 745 | if (!err) { |
733 | if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) { | 746 | if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) { |
734 | make_bad_inode(inode); | 747 | make_bad_inode(inode); |
735 | err = -EIO; | 748 | err = -EIO; |
736 | } else { | 749 | } else { |
737 | fuse_change_attributes(inode, &arg.attr, | 750 | fuse_change_attributes(inode, &outarg.attr, |
738 | attr_timeout(&arg), | 751 | attr_timeout(&outarg), |
739 | attr_version); | 752 | attr_version); |
740 | if (stat) | 753 | if (stat) |
741 | fuse_fillattr(inode, &arg.attr, stat); | 754 | fuse_fillattr(inode, &outarg.attr, stat); |
742 | } | 755 | } |
743 | } | 756 | } |
744 | return err; | 757 | return err; |
@@ -833,7 +846,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
833 | ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { | 846 | ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { |
834 | struct fuse_inode *fi = get_fuse_inode(inode); | 847 | struct fuse_inode *fi = get_fuse_inode(inode); |
835 | if (fi->i_time < get_jiffies_64()) { | 848 | if (fi->i_time < get_jiffies_64()) { |
836 | err = fuse_do_getattr(inode, NULL); | 849 | err = fuse_do_getattr(inode, NULL, NULL); |
837 | if (err) | 850 | if (err) |
838 | return err; | 851 | return err; |
839 | 852 | ||
@@ -848,7 +861,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
848 | attributes. This is also needed, because the root | 861 | attributes. This is also needed, because the root |
849 | node will at first have no permissions */ | 862 | node will at first have no permissions */ |
850 | if (err == -EACCES && !refreshed) { | 863 | if (err == -EACCES && !refreshed) { |
851 | err = fuse_do_getattr(inode, NULL); | 864 | err = fuse_do_getattr(inode, NULL, NULL); |
852 | if (!err) | 865 | if (!err) |
853 | err = generic_permission(inode, mask, NULL); | 866 | err = generic_permission(inode, mask, NULL); |
854 | } | 867 | } |
@@ -864,7 +877,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
864 | if (refreshed) | 877 | if (refreshed) |
865 | return -EACCES; | 878 | return -EACCES; |
866 | 879 | ||
867 | err = fuse_do_getattr(inode, NULL); | 880 | err = fuse_do_getattr(inode, NULL, NULL); |
868 | if (!err && !(inode->i_mode & S_IXUGO)) | 881 | if (!err && !(inode->i_mode & S_IXUGO)) |
869 | return -EACCES; | 882 | return -EACCES; |
870 | } | 883 | } |
@@ -1107,7 +1120,7 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, | |||
1107 | return -EACCES; | 1120 | return -EACCES; |
1108 | 1121 | ||
1109 | if (fi->i_time < get_jiffies_64()) | 1122 | if (fi->i_time < get_jiffies_64()) |
1110 | err = fuse_do_getattr(inode, stat); | 1123 | err = fuse_do_getattr(inode, stat, NULL); |
1111 | else { | 1124 | else { |
1112 | err = 0; | 1125 | err = 0; |
1113 | generic_fillattr(inode, stat); | 1126 | generic_fillattr(inode, stat); |