Round the size of a cachefile up to DIO block size so that we can always read back the last partial page of a file using direct I/O. Signed-off-by: David Howells <dhowells@xxxxxxxxxx> --- fs/cachefiles/interface.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index a20917cb4667..0e3d5b5ffc55 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -184,6 +184,17 @@ static void cachefiles_update_object(struct fscache_object *_object) cachefiles_remove_object_xattr(cache, object->dentry); goto out; } + + object_size = round_up(object_size, CACHEFILES_DIO_BLOCK_SIZE); + _debug("trunc %llx -> %llx", i_size_read(d_inode(object->dentry)), object_size); + if (i_size_read(d_inode(object->dentry)) < object_size) { + ret = vfs_truncate(&path, object_size); + if (ret < 0) { + cachefiles_io_error_obj(object, "Trunc-to-dio-size failed"); + cachefiles_remove_object_xattr(cache, object->dentry); + goto out; + } + } } cachefiles_set_object_xattr(object, XATTR_REPLACE); @@ -354,6 +365,7 @@ static int cachefiles_attr_changed(struct cachefiles_object *object) int ret; ni_size = object->fscache.cookie->object_size; + ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE); _enter("{OBJ%x},[%llu]", object->fscache.debug_id, (unsigned long long) ni_size); @@ -422,6 +434,7 @@ static bool cachefiles_invalidate_object(struct fscache_object *_object) struct cachefiles_cache, cache); ni_size = object->fscache.cookie->object_size; + ni_size = round_up(ni_size, CACHEFILES_DIO_BLOCK_SIZE); _enter("{OBJ%x},[%llu]", object->fscache.debug_id, (unsigned long long)ni_size);