aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-10-17 02:31:02 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:43:04 -0400
commit244f6385c2891e366a7de5f6746ccc257efd8952 (patch)
tree09d51e0f55d9e88dad48941cc0a63e0253306e47 /fs/fuse
parent074406fa6309ab8b0aca15496b16b3653e58c03d (diff)
fuse: refresh stale attributes in fuse_permission()
fuse_permission() didn't refresh inode attributes before using them, even if the validity has already expired. Thanks to Junjiro Okajima for spotting this. Also remove some old code to unconditionally refresh the attributes on the root inode. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dir.c61
-rw-r--r--fs/fuse/file.c8
-rw-r--r--fs/fuse/fuse_i.h5
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
666int fuse_do_getattr(struct inode *inode) 666static 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 */
735static 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
750static int fuse_access(struct inode *inode, int mask) 726static 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)
794static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) 770static 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
829static int parse_dirfile(char *buf, size_t nbytes, struct file *file, 821static 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);
533void fuse_abort_conn(struct fuse_conn *fc); 533void fuse_abort_conn(struct fuse_conn *fc);
534 534
535/** 535/**
536 * Get the attributes of a file
537 */
538int fuse_do_getattr(struct inode *inode);
539
540/**
541 * Invalidate inode attributes 536 * Invalidate inode attributes
542 */ 537 */
543void fuse_invalidate_attr(struct inode *inode); 538void fuse_invalidate_attr(struct inode *inode);