diff options
-rw-r--r-- | fs/fuse/dir.c | 48 | ||||
-rw-r--r-- | fs/fuse/file.c | 21 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 3 |
3 files changed, 52 insertions, 20 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 | ||
778 | int 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 | ||
1194 | static int fuse_setxattr(struct dentry *entry, const char *name, | 1204 | static int fuse_setxattr(struct dentry *entry, const char *name, |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 535b37399009..474968fbb555 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -453,6 +453,25 @@ out: | |||
453 | return err; | 453 | return err; |
454 | } | 454 | } |
455 | 455 | ||
456 | static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | ||
457 | unsigned long nr_segs, loff_t pos) | ||
458 | { | ||
459 | struct inode *inode = iocb->ki_filp->f_mapping->host; | ||
460 | |||
461 | if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { | ||
462 | int err; | ||
463 | /* | ||
464 | * If trying to read past EOF, make sure the i_size | ||
465 | * attribute is up-to-date. | ||
466 | */ | ||
467 | err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); | ||
468 | if (err) | ||
469 | return err; | ||
470 | } | ||
471 | |||
472 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
473 | } | ||
474 | |||
456 | static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | 475 | static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, |
457 | struct inode *inode, loff_t pos, size_t count, | 476 | struct inode *inode, loff_t pos, size_t count, |
458 | int writepage) | 477 | int writepage) |
@@ -887,7 +906,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | |||
887 | static const struct file_operations fuse_file_operations = { | 906 | static const struct file_operations fuse_file_operations = { |
888 | .llseek = generic_file_llseek, | 907 | .llseek = generic_file_llseek, |
889 | .read = do_sync_read, | 908 | .read = do_sync_read, |
890 | .aio_read = generic_file_aio_read, | 909 | .aio_read = fuse_file_aio_read, |
891 | .write = do_sync_write, | 910 | .write = do_sync_write, |
892 | .aio_write = generic_file_aio_write, | 911 | .aio_write = generic_file_aio_write, |
893 | .mmap = fuse_file_mmap, | 912 | .mmap = fuse_file_mmap, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6c5461de1a5f..19b0129c9811 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -593,3 +593,6 @@ int fuse_valid_type(int m); | |||
593 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); | 593 | int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); |
594 | 594 | ||
595 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); | 595 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); |
596 | |||
597 | int fuse_update_attributes(struct inode *inode, struct kstat *stat, | ||
598 | struct file *file, bool *refreshed); | ||