From 67139e36d970418a7881636820658766ef395455 Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Fri, 15 Jul 2022 23:41:53 +0800 Subject: [PATCH] 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 Signed-off-by: Gao Xiang Link: https://lore.kernel.org/r/20220715154203.48093-7-hsiangkao@linux.alibaba.com --- fs/erofs/zdata.c | 132 ++++++++++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 52 deletions(-) diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 6295f3312f6f..423d4daf7ed9 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -913,6 +913,76 @@ static int z_erofs_parse_out_bvecs(struct z_erofs_pcluster *pcl, 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, struct z_erofs_pcluster *pcl, struct page **pagepool) @@ -957,54 +1027,11 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, pages[i] = NULL; err = z_erofs_parse_out_bvecs(pcl, pages, pagepool); - - overlapped = false; - compressed_pages = pcl->compressed_pages; - - for (i = 0; i < pclusterpages; ++i) { - 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; - } + compressed_pages = z_erofs_parse_in_bvecs(sbi, pcl, pages, + pagepool, &overlapped); + if (IS_ERR(compressed_pages)) { + err = PTR_ERR(compressed_pages); + compressed_pages = NULL; } if (err) @@ -1040,21 +1067,22 @@ static int z_erofs_decompress_pcluster(struct super_block *sb, out: /* must handle all compressed pages before actual file pages */ if (z_erofs_is_inline_pcluster(pcl)) { - page = compressed_pages[0]; - WRITE_ONCE(compressed_pages[0], NULL); + page = pcl->compressed_pages[0]; + WRITE_ONCE(pcl->compressed_pages[0], NULL); put_page(page); } else { for (i = 0; i < pclusterpages; ++i) { - page = compressed_pages[i]; + page = pcl->compressed_pages[i]; if (erofs_page_is_managed(sbi, page)) continue; /* recycle all individual short-lived pages */ (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) { page = pages[i];