aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dir.c48
-rw-r--r--fs/fuse/file.c21
-rw-r--r--fs/fuse/fuse_i.h3
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
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,
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
456static 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
456static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, 475static 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)
887static const struct file_operations fuse_file_operations = { 906static 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);
593int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task); 593int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task);
594 594
595u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); 595u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id);
596
597int fuse_update_attributes(struct inode *inode, struct kstat *stat,
598 struct file *file, bool *refreshed);