Commit c665b394 authored by Jeffle Xu's avatar Jeffle Xu Committed by Gao Xiang

erofs: implement fscache-based data readahead

Implement fscache-based data readahead. Also registers an individual
bdi for each erofs instance to enable readahead.
Signed-off-by: default avatarJeffle Xu <jefflexu@linux.alibaba.com>
Reviewed-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20220425122143.56815-21-jefflexu@linux.alibaba.comAcked-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
parent bd735bda
...@@ -162,12 +162,102 @@ static int erofs_fscache_readpage(struct file *file, struct page *page) ...@@ -162,12 +162,102 @@ static int erofs_fscache_readpage(struct file *file, struct page *page)
return ret; return ret;
} }
static void erofs_fscache_unlock_folios(struct readahead_control *rac,
size_t len)
{
while (len) {
struct folio *folio = readahead_folio(rac);
len -= folio_size(folio);
folio_mark_uptodate(folio);
folio_unlock(folio);
}
}
static void erofs_fscache_readahead(struct readahead_control *rac)
{
struct inode *inode = rac->mapping->host;
struct super_block *sb = inode->i_sb;
size_t len, count, done = 0;
erofs_off_t pos;
loff_t start, offset;
int ret;
if (!readahead_count(rac))
return;
start = readahead_pos(rac);
len = readahead_length(rac);
do {
struct erofs_map_blocks map;
struct erofs_map_dev mdev;
pos = start + done;
map.m_la = pos;
ret = erofs_map_blocks(inode, &map, EROFS_GET_BLOCKS_RAW);
if (ret)
return;
offset = start + done;
count = min_t(size_t, map.m_llen - (pos - map.m_la),
len - done);
if (!(map.m_flags & EROFS_MAP_MAPPED)) {
struct iov_iter iter;
iov_iter_xarray(&iter, READ, &rac->mapping->i_pages,
offset, count);
iov_iter_zero(count, &iter);
erofs_fscache_unlock_folios(rac, count);
ret = count;
continue;
}
if (map.m_flags & EROFS_MAP_META) {
struct folio *folio = readahead_folio(rac);
ret = erofs_fscache_readpage_inline(folio, &map);
if (!ret) {
folio_mark_uptodate(folio);
ret = folio_size(folio);
}
folio_unlock(folio);
continue;
}
mdev = (struct erofs_map_dev) {
.m_deviceid = map.m_deviceid,
.m_pa = map.m_pa,
};
ret = erofs_map_dev(sb, &mdev);
if (ret)
return;
ret = erofs_fscache_read_folios(mdev.m_fscache->cookie,
rac->mapping, offset, count,
mdev.m_pa + (pos - map.m_la));
/*
* For the error cases, the folios will be unlocked when
* .readahead() returns.
*/
if (!ret) {
erofs_fscache_unlock_folios(rac, count);
ret = count;
}
} while (ret > 0 && ((done += ret) < len));
}
static const struct address_space_operations erofs_fscache_meta_aops = { static const struct address_space_operations erofs_fscache_meta_aops = {
.readpage = erofs_fscache_meta_readpage, .readpage = erofs_fscache_meta_readpage,
}; };
const struct address_space_operations erofs_fscache_access_aops = { const struct address_space_operations erofs_fscache_access_aops = {
.readpage = erofs_fscache_readpage, .readpage = erofs_fscache_readpage,
.readahead = erofs_fscache_readahead,
}; };
int erofs_fscache_register_cookie(struct super_block *sb, int erofs_fscache_register_cookie(struct super_block *sb,
......
...@@ -658,6 +658,10 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc) ...@@ -658,6 +658,10 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
sbi->opt.fsid, true); sbi->opt.fsid, true);
if (err) if (err)
return err; return err;
err = super_setup_bdi(sb);
if (err)
return err;
} else { } else {
if (!sb_set_blocksize(sb, EROFS_BLKSIZ)) { if (!sb_set_blocksize(sb, EROFS_BLKSIZ)) {
erofs_err(sb, "failed to set erofs blksize"); erofs_err(sb, "failed to set erofs blksize");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment