@@ -12,6 +12,7 @@
struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr)
{
struct address_space * mapping;
+ struct erofs_sb_info *sbi;
struct page *page;
if (sb->s_bdev) {
@@ -19,8 +20,8 @@ struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr)
page = read_cache_page_gfp(mapping, blkaddr,
mapping_gfp_constraint(mapping, ~__GFP_FS));
} else {
- /* TODO: fscache based data path */
- page = ERR_PTR(-EINVAL);
+ sbi = EROFS_SB(sb);
+ page = erofs_readpage_from_fscache(sbi->bootstrap, blkaddr);
}
/* should already be PageUptodate */
@@ -1,5 +1,50 @@
#include "internal.h"
+static int erofs_begin_cache_operation(struct netfs_read_request *rreq)
+{
+ return fscache_begin_read_operation(&rreq->cache_resources,
+ rreq->netfs_priv);
+}
+
+static void erofs_priv_cleanup(struct address_space *mapping, void *netfs_priv)
+{
+}
+
+const struct netfs_read_request_ops erofs_req_ops = {
+ .begin_cache_operation = erofs_begin_cache_operation,
+ .cleanup = erofs_priv_cleanup,
+};
+
+struct page *erofs_readpage_from_fscache(struct fscache_cookie *cookie,
+ pgoff_t index)
+{
+ int ret = -ENOMEM;
+ struct folio *folio;
+ struct page *page;
+
+ page = alloc_page(GFP_KERNEL);
+ if (unlikely(!page)) {
+ printk("failed to allocate page\n");
+ goto err;
+ }
+
+ page->index = index;
+ folio = page_folio(page);
+
+ ret = netfs_readpage_demand(folio, &erofs_req_ops, cookie);
+ if (unlikely(ret || !PageUptodate(page))) {
+ printk("failed to read from fscache\n");
+ goto err_page;
+ }
+
+ return page;
+
+err_page:
+ __free_page(page);
+err:
+ return ERR_PTR(ret);
+}
+
int erofs_fscache_init(struct erofs_sb_info *sbi, char *bootstrap_path)
{
sbi->volume = fscache_acquire_volume("erofs", NULL, 0);
@@ -577,6 +577,9 @@ static inline int z_erofs_load_lzma_config(struct super_block *sb,
int erofs_fscache_init(struct erofs_sb_info *sbi, char *bootstrap_path);
void erofs_fscache_cleanup(struct erofs_sb_info *sbi);
+struct page *erofs_readpage_from_fscache(struct fscache_cookie *cookie,
+ pgoff_t index);
+
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
#endif /* __EROFS_INTERNAL_H */
@@ -330,21 +330,23 @@ static int erofs_init_devices(struct super_block *sb,
static int erofs_read_superblock(struct super_block *sb)
{
- struct erofs_sb_info *sbi;
+ struct erofs_sb_info *sbi = EROFS_SB(sb);
struct page *page;
struct erofs_super_block *dsb;
unsigned int blkszbits;
void *data;
int ret;
- page = read_mapping_page(sb->s_bdev->bd_inode->i_mapping, 0, NULL);
+ if (sb->s_bdev)
+ page = read_mapping_page(sb->s_bdev->bd_inode->i_mapping, 0, NULL);
+ else
+ page = erofs_readpage_from_fscache(sbi->bootstrap, 0);
+
if (IS_ERR(page)) {
erofs_err(sb, "cannot read erofs superblock");
return PTR_ERR(page);
}
- sbi = EROFS_SB(sb);
-
data = kmap(page);
dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET);
Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com> --- fs/erofs/data.c | 5 +++-- fs/erofs/fscache.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ fs/erofs/internal.h | 3 +++ fs/erofs/super.c | 10 ++++++---- 4 files changed, 57 insertions(+), 6 deletions(-)