mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 13:53:33 +00:00
erofs: introduce `z_erofs_parse_in_bvecs'
`z_erofs_decompress_pcluster()' is too long therefore it'd be better to introduce another helper to parse compressed pages (or laterly, compressed bvecs.) BTW, since `compressed_bvecs' is too long as a part of the function name, `in_bvecs' is used here instead. Acked-by: Chao Yu <chao@kernel.org> Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com> Link: https://lore.kernel.org/r/20220715154203.48093-7-hsiangkao@linux.alibaba.com
This commit is contained in:
parent
387bab8716
commit
67139e36d9
1 changed files with 80 additions and 52 deletions
132
fs/erofs/zdata.c
132
fs/erofs/zdata.c
|
@ -913,6 +913,76 @@ static int z_erofs_parse_out_bvecs(struct z_erofs_pcluster *pcl,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct page **z_erofs_parse_in_bvecs(struct erofs_sb_info *sbi,
|
||||||
|
struct z_erofs_pcluster *pcl, struct page **pages,
|
||||||
|
struct page **pagepool, bool *overlapped)
|
||||||
|
{
|
||||||
|
unsigned int pclusterpages = z_erofs_pclusterpages(pcl);
|
||||||
|
struct page **compressed_pages;
|
||||||
|
int i, err = 0;
|
||||||
|
|
||||||
|
/* XXX: will have a better approach in the following commits */
|
||||||
|
compressed_pages = kmalloc_array(pclusterpages, sizeof(struct page *),
|
||||||
|
GFP_KERNEL | __GFP_NOFAIL);
|
||||||
|
*overlapped = false;
|
||||||
|
|
||||||
|
for (i = 0; i < pclusterpages; ++i) {
|
||||||
|
unsigned int pagenr;
|
||||||
|
struct page *page = pcl->compressed_pages[i];
|
||||||
|
|
||||||
|
/* compressed pages ought to be present before decompressing */
|
||||||
|
if (!page) {
|
||||||
|
DBG_BUGON(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
compressed_pages[i] = page;
|
||||||
|
|
||||||
|
if (z_erofs_is_inline_pcluster(pcl)) {
|
||||||
|
if (!PageUptodate(page))
|
||||||
|
err = -EIO;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG_BUGON(z_erofs_page_is_invalidated(page));
|
||||||
|
if (!z_erofs_is_shortlived_page(page)) {
|
||||||
|
if (erofs_page_is_managed(sbi, page)) {
|
||||||
|
if (!PageUptodate(page))
|
||||||
|
err = -EIO;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* only if non-head page can be selected
|
||||||
|
* for inplace decompression
|
||||||
|
*/
|
||||||
|
pagenr = z_erofs_onlinepage_index(page);
|
||||||
|
|
||||||
|
DBG_BUGON(pagenr >= pcl->nr_pages);
|
||||||
|
if (pages[pagenr]) {
|
||||||
|
DBG_BUGON(1);
|
||||||
|
SetPageError(pages[pagenr]);
|
||||||
|
z_erofs_onlinepage_endio(pages[pagenr]);
|
||||||
|
err = -EFSCORRUPTED;
|
||||||
|
}
|
||||||
|
pages[pagenr] = page;
|
||||||
|
|
||||||
|
*overlapped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PG_error needs checking for all non-managed pages */
|
||||||
|
if (PageError(page)) {
|
||||||
|
DBG_BUGON(PageUptodate(page));
|
||||||
|
err = -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
kfree(compressed_pages);
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
return compressed_pages;
|
||||||
|
}
|
||||||
|
|
||||||
static int z_erofs_decompress_pcluster(struct super_block *sb,
|
static int z_erofs_decompress_pcluster(struct super_block *sb,
|
||||||
struct z_erofs_pcluster *pcl,
|
struct z_erofs_pcluster *pcl,
|
||||||
struct page **pagepool)
|
struct page **pagepool)
|
||||||
|
@ -957,54 +1027,11 @@ static int z_erofs_decompress_pcluster(struct super_block *sb,
|
||||||
pages[i] = NULL;
|
pages[i] = NULL;
|
||||||
|
|
||||||
err = z_erofs_parse_out_bvecs(pcl, pages, pagepool);
|
err = z_erofs_parse_out_bvecs(pcl, pages, pagepool);
|
||||||
|
compressed_pages = z_erofs_parse_in_bvecs(sbi, pcl, pages,
|
||||||
overlapped = false;
|
pagepool, &overlapped);
|
||||||
compressed_pages = pcl->compressed_pages;
|
if (IS_ERR(compressed_pages)) {
|
||||||
|
err = PTR_ERR(compressed_pages);
|
||||||
for (i = 0; i < pclusterpages; ++i) {
|
compressed_pages = NULL;
|
||||||
unsigned int pagenr;
|
|
||||||
|
|
||||||
page = compressed_pages[i];
|
|
||||||
/* all compressed pages ought to be valid */
|
|
||||||
DBG_BUGON(!page);
|
|
||||||
|
|
||||||
if (z_erofs_is_inline_pcluster(pcl)) {
|
|
||||||
if (!PageUptodate(page))
|
|
||||||
err = -EIO;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG_BUGON(z_erofs_page_is_invalidated(page));
|
|
||||||
if (!z_erofs_is_shortlived_page(page)) {
|
|
||||||
if (erofs_page_is_managed(sbi, page)) {
|
|
||||||
if (!PageUptodate(page))
|
|
||||||
err = -EIO;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* only if non-head page can be selected
|
|
||||||
* for inplace decompression
|
|
||||||
*/
|
|
||||||
pagenr = z_erofs_onlinepage_index(page);
|
|
||||||
|
|
||||||
DBG_BUGON(pagenr >= nr_pages);
|
|
||||||
if (pages[pagenr]) {
|
|
||||||
DBG_BUGON(1);
|
|
||||||
SetPageError(pages[pagenr]);
|
|
||||||
z_erofs_onlinepage_endio(pages[pagenr]);
|
|
||||||
err = -EFSCORRUPTED;
|
|
||||||
}
|
|
||||||
pages[pagenr] = page;
|
|
||||||
|
|
||||||
overlapped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PG_error needs checking for all non-managed pages */
|
|
||||||
if (PageError(page)) {
|
|
||||||
DBG_BUGON(PageUptodate(page));
|
|
||||||
err = -EIO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1040,21 +1067,22 @@ static int z_erofs_decompress_pcluster(struct super_block *sb,
|
||||||
out:
|
out:
|
||||||
/* must handle all compressed pages before actual file pages */
|
/* must handle all compressed pages before actual file pages */
|
||||||
if (z_erofs_is_inline_pcluster(pcl)) {
|
if (z_erofs_is_inline_pcluster(pcl)) {
|
||||||
page = compressed_pages[0];
|
page = pcl->compressed_pages[0];
|
||||||
WRITE_ONCE(compressed_pages[0], NULL);
|
WRITE_ONCE(pcl->compressed_pages[0], NULL);
|
||||||
put_page(page);
|
put_page(page);
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < pclusterpages; ++i) {
|
for (i = 0; i < pclusterpages; ++i) {
|
||||||
page = compressed_pages[i];
|
page = pcl->compressed_pages[i];
|
||||||
|
|
||||||
if (erofs_page_is_managed(sbi, page))
|
if (erofs_page_is_managed(sbi, page))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* recycle all individual short-lived pages */
|
/* recycle all individual short-lived pages */
|
||||||
(void)z_erofs_put_shortlivedpage(pagepool, page);
|
(void)z_erofs_put_shortlivedpage(pagepool, page);
|
||||||
WRITE_ONCE(compressed_pages[i], NULL);
|
WRITE_ONCE(pcl->compressed_pages[i], NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
kfree(compressed_pages);
|
||||||
|
|
||||||
for (i = 0; i < nr_pages; ++i) {
|
for (i = 0; i < nr_pages; ++i) {
|
||||||
page = pages[i];
|
page = pages[i];
|
||||||
|
|
Loading…
Reference in a new issue