Commit 11152496 authored by Gao Xiang's avatar Gao Xiang Committed by Greg Kroah-Hartman

staging: erofs: fix error handling when failed to read compresssed data

Complete read error handling paths for all three kinds of
compressed pages:

 1) For cache-managed pages, PG_uptodate will be checked since
    read_endio will unlock and SetPageUptodate for these pages;

 2) For inplaced pages, read_endio cannot SetPageUptodate directly
    since it should be used to mark the final decompressed data,
    PG_error will be set with page locked for IO error instead;

 3) For staging pages, PG_error is used, which is similar to
    what we do for inplaced pages.

Fixes: 3883a79a ("staging: erofs: introduce VLE decompression support")
Cc: <stable@vger.kernel.org> # 4.19+
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarGao Xiang <gaoxiang25@huawei.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c8723cb8
...@@ -973,6 +973,7 @@ static int z_erofs_vle_unzip(struct super_block *sb, ...@@ -973,6 +973,7 @@ static int z_erofs_vle_unzip(struct super_block *sb,
overlapped = false; overlapped = false;
compressed_pages = grp->compressed_pages; compressed_pages = grp->compressed_pages;
err = 0;
for (i = 0; i < clusterpages; ++i) { for (i = 0; i < clusterpages; ++i) {
unsigned int pagenr; unsigned int pagenr;
...@@ -982,26 +983,39 @@ static int z_erofs_vle_unzip(struct super_block *sb, ...@@ -982,26 +983,39 @@ static int z_erofs_vle_unzip(struct super_block *sb,
DBG_BUGON(!page); DBG_BUGON(!page);
DBG_BUGON(!page->mapping); DBG_BUGON(!page->mapping);
if (z_erofs_is_stagingpage(page)) if (!z_erofs_is_stagingpage(page)) {
continue;
#ifdef EROFS_FS_HAS_MANAGED_CACHE #ifdef EROFS_FS_HAS_MANAGED_CACHE
if (page->mapping == MNGD_MAPPING(sbi)) { if (page->mapping == MNGD_MAPPING(sbi)) {
DBG_BUGON(!PageUptodate(page)); if (unlikely(!PageUptodate(page)))
continue; err = -EIO;
} continue;
}
#endif #endif
/* only non-head page could be reused as a compressed page */ /*
pagenr = z_erofs_onlinepage_index(page); * only if non-head page can be selected
* for inplace decompression
*/
pagenr = z_erofs_onlinepage_index(page);
DBG_BUGON(pagenr >= nr_pages); DBG_BUGON(pagenr >= nr_pages);
DBG_BUGON(pages[pagenr]); DBG_BUGON(pages[pagenr]);
++sparsemem_pages; ++sparsemem_pages;
pages[pagenr] = page; pages[pagenr] = page;
overlapped = true;
}
overlapped = true; /* PG_error needs checking for inplaced and staging pages */
if (unlikely(PageError(page))) {
DBG_BUGON(PageUptodate(page));
err = -EIO;
}
} }
if (unlikely(err))
goto out;
llen = (nr_pages << PAGE_SHIFT) - work->pageofs; llen = (nr_pages << PAGE_SHIFT) - work->pageofs;
if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) { if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) {
...@@ -1195,6 +1209,7 @@ pickup_page_for_submission(struct z_erofs_vle_workgroup *grp, ...@@ -1195,6 +1209,7 @@ pickup_page_for_submission(struct z_erofs_vle_workgroup *grp,
if (page->mapping == mc) { if (page->mapping == mc) {
WRITE_ONCE(grp->compressed_pages[nr], page); WRITE_ONCE(grp->compressed_pages[nr], page);
ClearPageError(page);
if (!PagePrivate(page)) { if (!PagePrivate(page)) {
/* /*
* impossible to be !PagePrivate(page) for * impossible to be !PagePrivate(page) for
......
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