From: Brian F. <bf...@re...> - 2012-07-10 14:36:57
|
A fuse-based network filesystem might allow for the inode and/or file data to change unexpectedly. A local client that opens and repeatedly reads a file might never pick up on such changes and indefinitely return stale data. Always invoke fuse_update_attributes() in the read path to cause an attr revalidation when the attributes expire. This leads to a page cache invalidation if necessary and ensures fuse issues new read requests to the fuse client. The original logic (reval only on reads beyond EOF) is preserved if the client specifies FUSE_LEGACY_CACHE on init. Signed-off-by: Brian Foster <bf...@re...> --- fs/fuse/file.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index b321a68..6f3fe78 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -703,12 +703,15 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct inode *inode = iocb->ki_filp->f_mapping->host; + struct fuse_conn *fc = get_fuse_conn(inode); - if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { + if (!fc->legacy_cache || + (pos + iov_length(iov, nr_segs) > i_size_read(inode))) { int err; /* - * If trying to read past EOF, make sure the i_size - * attribute is up-to-date. + * In legacy cache mode, update attributes only if we attempt + * to read past EOF (to ensure i_size is up to date). Otherwise, + * always update attributes on read. */ err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); if (err) -- 1.7.7.6 |