From: Jingbo Xu jefflexu@linux.alibaba.com
anolis inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB5UKT
Reference: https://gitee.com/anolis/cloud-kernel/commit/d1a5c14b77b3
--------------------------------
ANBZ: #2056
Allocate and initialize the file descriptor of the backing file at the lookup phase, in prep for the following support for readahead in on-demand mode. This file descriptor is only maintained in on-demand mode.
One thing worth noting is that, the file descriptor is opened with FMODE_RANDOM, so that the following page_cache_sync_ra() will fallback to force_page_cache_ra(). The following readahead routine in on-demand mode will trigger force readahead on backing files to read from backing files. We'd better make the implementation self-contained so that later the related kernel modules can be distributed and deployed directly without upgrading the kernel. However force_page_cache_ra() is not exported. To work around this, set FMODE_RANDOM on the file descriptor, and call page_cache_sync_readahead() instead.
Besides, implement the write routine of the anonymous fd with buffer IO instead, which can also be facilitated from the pre-allocated file descriptor.
Signed-off-by: Jingbo Xu jefflexu@linux.alibaba.com Link: https://gitee.com/anolis/cloud-kernel/pulls/692 Reviewed-by: Joseph Qi joseph.qi@linux.alibaba.com Signed-off-by: Baokun Li libaokun1@huawei.com --- fs/cachefiles/interface.c | 6 ++++++ fs/cachefiles/internal.h | 1 + fs/cachefiles/namei.c | 18 ++++++++++++++++++ fs/cachefiles/ondemand.c | 20 ++------------------ 4 files changed, 27 insertions(+), 18 deletions(-)
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 80a241638452..60b6ca443e8e 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -308,6 +308,12 @@ static void cachefiles_drop_object(struct fscache_object *_object) object->backer = NULL; }
+ /* clean up file descriptor for non-index object */ + if (object->file) { + fput(object->file); + object->file = NULL; + } + /* note that the object is now inactive */ if (test_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) cachefiles_mark_object_inactive(cache, object, i_blocks); diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index cff061f208f6..ab0ca3b1cd08 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -39,6 +39,7 @@ struct cachefiles_object { struct cachefiles_lookup_data *lookup_data; /* cached lookup data */ struct dentry *dentry; /* the file/dir representing this object */ struct dentry *backer; /* backing file */ + struct file *file; /* backing file in on-demand mode */ loff_t i_size; /* object size */ unsigned long flags; #define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */ diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 22a409669fd0..3c7168d0beec 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -705,6 +705,24 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, if (object->dentry->d_sb->s_blocksize > PAGE_SIZE) goto check_error;
+ if (cachefiles_in_ondemand_mode(cache)) { + struct path path; + struct file *file; + + path.mnt = cache->mnt; + path.dentry = object->dentry; + file = dentry_open(&path, O_RDWR | O_LARGEFILE, + cache->cache_cred); + if (IS_ERR(file)) + goto check_error; + /* + * so that page_cache_sync_readahead() will fallback + * to force_page_cache_readahead() + */ + file->f_mode |= FMODE_RANDOM; + object->file = file; + } + object->backer = object->dentry; } else { BUG(); // TODO: open file in data-class subdir diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c index bebc2f8627d8..250b98e9820c 100644 --- a/fs/cachefiles/ondemand.c +++ b/fs/cachefiles/ondemand.c @@ -51,30 +51,14 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb, struct iov_iter *iter) { struct cachefiles_object *object = kiocb->ki_filp->private_data; - struct cachefiles_cache *cache; size_t len = iter->count; loff_t pos = kiocb->ki_pos; - struct path path; - struct file *file; int ret;
- if (!object->backer) - return -ENOBUFS; - - cache = container_of(object->fscache.cache, - struct cachefiles_cache, cache); - - /* write data to the backing filesystem and let it store it in its - * own time */ - path.mnt = cache->mnt; - path.dentry = object->backer; - file = dentry_open(&path, O_RDWR | O_LARGEFILE | O_DIRECT, - cache->cache_cred); - if (IS_ERR(file)) + if (!object->file) return -ENOBUFS;
- ret = vfs_iter_write(file, iter, &pos, 0); - fput(file); + ret = vfs_iter_write(object->file, iter, &pos, 0); if (ret != len) return -EIO; return len;