diff options
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r-- | fs/fuse/dir.c | 61 |
1 files changed, 31 insertions, 30 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 29fef75f2360..9ee2a6bbfa37 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -663,7 +663,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, | |||
663 | return err; | 663 | return err; |
664 | } | 664 | } |
665 | 665 | ||
666 | int fuse_do_getattr(struct inode *inode) | 666 | static int fuse_do_getattr(struct inode *inode) |
667 | { | 667 | { |
668 | int err; | 668 | int err; |
669 | struct fuse_attr_out arg; | 669 | struct fuse_attr_out arg; |
@@ -723,30 +723,6 @@ static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) | |||
723 | return 0; | 723 | return 0; |
724 | } | 724 | } |
725 | 725 | ||
726 | /* | ||
727 | * Check whether the inode attributes are still valid | ||
728 | * | ||
729 | * If the attribute validity timeout has expired, then fetch the fresh | ||
730 | * attributes with a 'getattr' request | ||
731 | * | ||
732 | * I'm not sure why cached attributes are never returned for the root | ||
733 | * inode, this is probably being too cautious. | ||
734 | */ | ||
735 | static int fuse_revalidate(struct dentry *entry) | ||
736 | { | ||
737 | struct inode *inode = entry->d_inode; | ||
738 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
739 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
740 | |||
741 | if (!fuse_allow_task(fc, current)) | ||
742 | return -EACCES; | ||
743 | if (get_node_id(inode) != FUSE_ROOT_ID && | ||
744 | fi->i_time >= get_jiffies_64()) | ||
745 | return 0; | ||
746 | |||
747 | return fuse_do_getattr(inode); | ||
748 | } | ||
749 | |||
750 | static int fuse_access(struct inode *inode, int mask) | 726 | static int fuse_access(struct inode *inode, int mask) |
751 | { | 727 | { |
752 | struct fuse_conn *fc = get_fuse_conn(inode); | 728 | struct fuse_conn *fc = get_fuse_conn(inode); |
@@ -794,16 +770,33 @@ static int fuse_access(struct inode *inode, int mask) | |||
794 | static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | 770 | static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) |
795 | { | 771 | { |
796 | struct fuse_conn *fc = get_fuse_conn(inode); | 772 | struct fuse_conn *fc = get_fuse_conn(inode); |
773 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
774 | bool refreshed = false; | ||
775 | int err = 0; | ||
797 | 776 | ||
798 | if (!fuse_allow_task(fc, current)) | 777 | if (!fuse_allow_task(fc, current)) |
799 | return -EACCES; | 778 | return -EACCES; |
800 | else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { | 779 | |
780 | /* | ||
781 | * If attributes are needed, but are stale, refresh them | ||
782 | * before proceeding | ||
783 | */ | ||
784 | if (((fc->flags & FUSE_DEFAULT_PERMISSIONS) || (mask & MAY_EXEC)) && | ||
785 | fi->i_time < get_jiffies_64()) { | ||
786 | err = fuse_do_getattr(inode); | ||
787 | if (err) | ||
788 | return err; | ||
789 | |||
790 | refreshed = true; | ||
791 | } | ||
792 | |||
793 | if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { | ||
801 | int err = generic_permission(inode, mask, NULL); | 794 | int err = generic_permission(inode, mask, NULL); |
802 | 795 | ||
803 | /* If permission is denied, try to refresh file | 796 | /* If permission is denied, try to refresh file |
804 | attributes. This is also needed, because the root | 797 | attributes. This is also needed, because the root |
805 | node will at first have no permissions */ | 798 | node will at first have no permissions */ |
806 | if (err == -EACCES) { | 799 | if (err == -EACCES && !refreshed) { |
807 | err = fuse_do_getattr(inode); | 800 | err = fuse_do_getattr(inode); |
808 | if (!err) | 801 | if (!err) |
809 | err = generic_permission(inode, mask, NULL); | 802 | err = generic_permission(inode, mask, NULL); |
@@ -814,7 +807,6 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
814 | noticed immediately, only after the attribute | 807 | noticed immediately, only after the attribute |
815 | timeout has expired */ | 808 | timeout has expired */ |
816 | 809 | ||
817 | return err; | ||
818 | } else { | 810 | } else { |
819 | int mode = inode->i_mode; | 811 | int mode = inode->i_mode; |
820 | if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) | 812 | if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) |
@@ -822,8 +814,8 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
822 | 814 | ||
823 | if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) | 815 | if (nd && (nd->flags & (LOOKUP_ACCESS | LOOKUP_CHDIR))) |
824 | return fuse_access(inode, mask); | 816 | return fuse_access(inode, mask); |
825 | return 0; | ||
826 | } | 817 | } |
818 | return err; | ||
827 | } | 819 | } |
828 | 820 | ||
829 | static int parse_dirfile(char *buf, size_t nbytes, struct file *file, | 821 | static int parse_dirfile(char *buf, size_t nbytes, struct file *file, |
@@ -1052,7 +1044,16 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, | |||
1052 | struct kstat *stat) | 1044 | struct kstat *stat) |
1053 | { | 1045 | { |
1054 | struct inode *inode = entry->d_inode; | 1046 | struct inode *inode = entry->d_inode; |
1055 | int err = fuse_revalidate(entry); | 1047 | struct fuse_inode *fi = get_fuse_inode(inode); |
1048 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
1049 | int err = 0; | ||
1050 | |||
1051 | if (!fuse_allow_task(fc, current)) | ||
1052 | return -EACCES; | ||
1053 | |||
1054 | if (fi->i_time < get_jiffies_64()) | ||
1055 | err = fuse_do_getattr(inode); | ||
1056 | |||
1056 | if (!err) | 1057 | if (!err) |
1057 | generic_fillattr(inode, stat); | 1058 | generic_fillattr(inode, stat); |
1058 | 1059 | ||