From: Gao Xiang hsiangkao@linux.alibaba.com
anolis inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IB5UKT
Reference: https://gitee.com/anolis/cloud-kernel/commit/a8d223ce9c5a
--------------------------------
ANBZ: #1666
commit 5375e7c8b0fef11645657384fe1f2cfed1e0baa7 upstream.
Implement the data plane of reading metadata from primary data blob over fscache.
Signed-off-by: Jeffle Xu jefflexu@linux.alibaba.com Reviewed-by: Gao Xiang hsiangkao@linux.alibaba.com Link: https://lore.kernel.org/r/20220425122143.56815-18-jefflexu@linux.alibaba.com Acked-by: Chao Yu chao@kernel.org Signed-off-by: Gao Xiang hsiangkao@linux.alibaba.com Signed-off-by: Huang Jianan jnhuang@linux.alibaba.com Reviewed-by: Jeffle Xu jefflexu@linux.alibaba.com Signed-off-by: Baokun Li libaokun1@huawei.com --- fs/erofs/data.c | 6 ++++- fs/erofs/fscache.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 8b4547dc32af..89f76d7a3452 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -34,9 +34,13 @@ static void erofs_readendio(struct bio *bio)
static struct page *erofs_read_meta_page(struct super_block *sb, pgoff_t index) { - struct address_space *const mapping = sb->s_bdev->bd_inode->i_mapping; + struct address_space *mapping; struct page *page;
+ if (erofs_is_fscache_mode(sb)) + mapping = EROFS_SB(sb)->s_fscache->inode->i_mapping; + else + mapping = sb->s_bdev->bd_inode->i_mapping; page = read_cache_page_gfp(mapping, index, mapping_gfp_constraint(mapping, ~__GFP_FS)); return page; diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c index 7659f8ae65c3..c922dda36bda 100644 --- a/fs/erofs/fscache.c +++ b/fs/erofs/fscache.c @@ -30,7 +30,69 @@ const struct fscache_cookie_def erofs_fscache_inode_object_def = { .type = FSCACHE_COOKIE_TYPE_DATAFILE, };
+static void erofs_readpage_from_fscache_complete(struct page *page, void *ctx, + int error) +{ + if (!error) + SetPageUptodate(page); + unlock_page(page); +} + +static int erofs_fscache_meta_readpage(struct file *data, struct page *page) +{ + int ret; + struct super_block *sb = page->mapping->host->i_sb; + struct erofs_map_dev mdev = { + .m_deviceid = 0, + .m_pa = page_offset(page), + }; + + ret = erofs_map_dev(sb, &mdev); + if (ret) + goto out; + + ret = fscache_read_or_alloc_page(mdev.m_fscache->cookie, page, + erofs_readpage_from_fscache_complete, + NULL, + GFP_KERNEL); + switch (ret) { + case 0: /* page found in fscache, read submitted */ + erofs_dbg("%s: submitted", __func__); + return ret; + case -ENOBUFS: /* page won't be cached */ + case -ENODATA: /* page not in cache */ + erofs_err(sb, "%s: %d", __func__, ret); + ret = -EIO; + goto out; + default: + erofs_err(sb, "unknown error ret = %d", ret); + } + +out: + unlock_page(page); + return ret; +} + +static int erofs_fscache_release_page(struct page *page, gfp_t gfp) +{ + if (WARN_ON(PagePrivate(page))) + return 0; + + ClearPageFsCache(page); + return 1; +} + +static void erofs_fscache_invalidate_page(struct page *page, unsigned int offset, + unsigned int length) +{ + if (offset == 0 && length == PAGE_SIZE) + ClearPageFsCache(page); +} + static const struct address_space_operations erofs_fscache_meta_aops = { + .readpage = erofs_fscache_meta_readpage, + .releasepage = erofs_fscache_release_page, + .invalidatepage = erofs_fscache_invalidate_page, };
int erofs_fscache_register_cookie(struct super_block *sb,