diff options
-rw-r--r-- | fs/fuse/dir.c | 61 | ||||
-rw-r--r-- | fs/fuse/file.c | 8 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 5 |
3 files changed, 31 insertions, 43 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 | ||
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index fb1713e76756..f3ef2bde983b 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -106,14 +106,6 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
106 | if (err) | 106 | if (err) |
107 | return err; | 107 | return err; |
108 | 108 | ||
109 | /* If opening the root node, no lookup has been performed on | ||
110 | it, so the attributes must be refreshed */ | ||
111 | if (get_node_id(inode) == FUSE_ROOT_ID) { | ||
112 | err = fuse_do_getattr(inode); | ||
113 | if (err) | ||
114 | return err; | ||
115 | } | ||
116 | |||
117 | ff = fuse_file_alloc(); | 109 | ff = fuse_file_alloc(); |
118 | if (!ff) | 110 | if (!ff) |
119 | return -ENOMEM; | 111 | return -ENOMEM; |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 60683b787250..e0555d68b4a7 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -533,11 +533,6 @@ void request_send_background(struct fuse_conn *fc, struct fuse_req *req); | |||
533 | void fuse_abort_conn(struct fuse_conn *fc); | 533 | void fuse_abort_conn(struct fuse_conn *fc); |
534 | 534 | ||
535 | /** | 535 | /** |
536 | * Get the attributes of a file | ||
537 | */ | ||
538 | int fuse_do_getattr(struct inode *inode); | ||
539 | |||
540 | /** | ||
541 | * Invalidate inode attributes | 536 | * Invalidate inode attributes |
542 | */ | 537 | */ |
543 | void fuse_invalidate_attr(struct inode *inode); | 538 | void fuse_invalidate_attr(struct inode *inode); |