When upper read-only fs uses fscache for demand reading, it has no idea on the size of the backed file. (You need to input the file size as the @object_size parameter when calling fscache_acquire_cookie().) In this using scenario, user daemon is responsible for preparing all backing files with correct file size (though they can be all sparse files), and the upper fs shall guarantee that past EOF access will never happen. Then with this precondition, cachefiles can detect the actual size of backing file, and set it as the size of backed file. Signed-off-by: Jeffle Xu <jefflexu@xxxxxxxxxxxxxxxxx> --- fs/cachefiles/namei.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 074722c21522..54123b2693cd 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -511,9 +511,19 @@ struct file *cachefiles_create_tmpfile(struct cachefiles_object *object) */ static bool cachefiles_create_file(struct cachefiles_object *object) { + struct cachefiles_cache *cache = object->volume->cache; struct file *file; int ret; + /* + * Demand read mode requires that backing files have been prepared with + * correct file size under corresponding directory. We can get here when + * the backing file doesn't exist under corresponding directory, or the + * file size is unexpected 0. + */ + if (test_bit(CACHEFILES_DEMAND_MODE, &cache->flags)) + return false; + ret = cachefiles_has_space(object->volume->cache, 1, 0, cachefiles_has_space_for_create); if (ret < 0) @@ -530,6 +540,32 @@ static bool cachefiles_create_file(struct cachefiles_object *object) return true; } +/* + * Fs using fscache for demand reading may have no idea of the file size of + * backing files. Thus the demand read mode requires that backing files have + * been prepared with correct file size under corresponding directory. Then + * fscache backend is responsible for taking the file size of the backing file + * as the object size. + */ +static int cachefiles_recheck_size(struct cachefiles_object *object, + struct file *file) +{ + loff_t size; + struct cachefiles_cache *cache = object->volume->cache; + + if (!test_bit(CACHEFILES_DEMAND_MODE, &cache->flags)) + return 0; + + size = i_size_read(file_inode(file)); + if (size) { + object->cookie->object_size = size; + return 0; + } else { + return -EINVAL; + } + +} + /* * Open an existing file, checking its attributes and replacing it if it is * stale. @@ -569,6 +605,10 @@ static bool cachefiles_open_file(struct cachefiles_object *object, } _debug("file -> %pd positive", dentry); + ret = cachefiles_recheck_size(object, file); + if (ret < 0) + goto check_failed; + ret = cachefiles_check_auxdata(object, file); if (ret < 0) goto check_failed; -- 2.27.0