When doing a direct/sync write, we need to invalidate the page cache in the range being written to. If we don't do this, the cache will include invalid data as we just did a write that avoided the page cache. Signed-off-by: Luís Henriques <lhenriques@xxxxxxx> --- fs/ceph/file.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) Changes since v3: - Dropped initial call to invalidate_inode_pages2_range() - Added extra comment to document invalidation Changes since v2: - Invalidation needs to be done after a write Changes since v1: - Replaced truncate_inode_pages_range() by invalidate_inode_pages2_range - Call fscache_invalidate with FSCACHE_INVAL_DIO_WRITE if we're doing DIO diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 5072570c2203..97f764b2fbdd 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1606,11 +1606,6 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos, return ret; ceph_fscache_invalidate(inode, false); - ret = invalidate_inode_pages2_range(inode->i_mapping, - pos >> PAGE_SHIFT, - (pos + count - 1) >> PAGE_SHIFT); - if (ret < 0) - dout("invalidate_inode_pages2_range returned %d\n", ret); while ((len = iov_iter_count(from)) > 0) { size_t left; @@ -1938,6 +1933,20 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos, break; } ceph_clear_error_write(ci); + + /* + * we need to invalidate the page cache here, otherwise the + * cache will include invalid data in direct/sync writes. + */ + ret = invalidate_inode_pages2_range( + inode->i_mapping, + pos >> PAGE_SHIFT, + (pos + len - 1) >> PAGE_SHIFT); + if (ret < 0) { + dout("invalidate_inode_pages2_range returned %d\n", + ret); + ret = 0; + } pos += len; written += len; dout("sync_write written %d\n", written);