aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dir.c
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-11-28 19:21:59 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-29 12:24:54 -0500
commitbcb4be809d2a804ff040d95db4a664113833e702 (patch)
tree11a3aad0dc7df29906e2b379d13f14ccf26c9b56 /fs/fuse/dir.c
parentb6fd6ecb830444636bc4e9d626f214082c91fffe (diff)
fuse: fix reading past EOF
Currently reading a fuse file will stop at cached i_size and return EOF, even though the file might have grown since the attributes were last updated. So detect if trying to read past EOF, and refresh the attributes before continuing with the read. Thanks to mpb for the report. 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/dir.c')
-rw-r--r--fs/fuse/dir.c48
1 files changed, 29 insertions, 19 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 3763757f9fe7..7b3df35cf196 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -775,6 +775,31 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
775 return err; 775 return err;
776} 776}
777 777
778int fuse_update_attributes(struct inode *inode, struct kstat *stat,
779 struct file *file, bool *refreshed)
780{
781 struct fuse_inode *fi = get_fuse_inode(inode);
782 int err;
783 bool r;
784
785 if (fi->i_time < get_jiffies_64()) {
786 r = true;
787 err = fuse_do_getattr(inode, stat, file);
788 } else {
789 r = false;
790 err = 0;
791 if (stat) {
792 generic_fillattr(inode, stat);
793 stat->mode = fi->orig_i_mode;
794 }
795 }
796
797 if (refreshed != NULL)
798 *refreshed = r;
799
800 return err;
801}
802
778/* 803/*
779 * Calling into a user-controlled filesystem gives the filesystem 804 * Calling into a user-controlled filesystem gives the filesystem
780 * daemon ptrace-like capabilities over the requester process. This 805 * daemon ptrace-like capabilities over the requester process. This
@@ -862,14 +887,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
862 */ 887 */
863 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || 888 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
864 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 889 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
865 struct fuse_inode *fi = get_fuse_inode(inode); 890 err = fuse_update_attributes(inode, NULL, NULL, &refreshed);
866 if (fi->i_time < get_jiffies_64()) { 891 if (err)
867 err = fuse_do_getattr(inode, NULL, NULL); 892 return err;
868 if (err)
869 return err;
870
871 refreshed = true;
872 }
873 } 893 }
874 894
875 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 895 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
@@ -1173,22 +1193,12 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1173 struct kstat *stat) 1193 struct kstat *stat)
1174{ 1194{
1175 struct inode *inode = entry->d_inode; 1195 struct inode *inode = entry->d_inode;
1176 struct fuse_inode *fi = get_fuse_inode(inode);
1177 struct fuse_conn *fc = get_fuse_conn(inode); 1196 struct fuse_conn *fc = get_fuse_conn(inode);
1178 int err;
1179 1197
1180 if (!fuse_allow_task(fc, current)) 1198 if (!fuse_allow_task(fc, current))
1181 return -EACCES; 1199 return -EACCES;
1182 1200
1183 if (fi->i_time < get_jiffies_64()) 1201 return fuse_update_attributes(inode, stat, NULL, NULL);
1184 err = fuse_do_getattr(inode, stat, NULL);
1185 else {
1186 err = 0;
1187 generic_fillattr(inode, stat);
1188 stat->mode = fi->orig_i_mode;
1189 }
1190
1191 return err;
1192} 1202}
1193 1203
1194static int fuse_setxattr(struct dentry *entry, const char *name, 1204static int fuse_setxattr(struct dentry *entry, const char *name,