mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
staging: erofs: fix error handling when failed to read compresssed data
commitb6391ac734upstream. 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:3883a79abd("staging: erofs: introduce VLE decompression support") Cc: <stable@vger.kernel.org> # 4.19+ Reviewed-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Gao Xiang <gaoxiang25@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
3a18eabaa7
commit
83bbd66b37
@@ -885,6 +885,7 @@ repeat:
|
||||
overlapped = false;
|
||||
compressed_pages = grp->compressed_pages;
|
||||
|
||||
err = 0;
|
||||
for (i = 0; i < clusterpages; ++i) {
|
||||
unsigned pagenr;
|
||||
|
||||
@@ -894,26 +895,39 @@ repeat:
|
||||
DBG_BUGON(page == NULL);
|
||||
DBG_BUGON(page->mapping == NULL);
|
||||
|
||||
if (z_erofs_is_stagingpage(page))
|
||||
continue;
|
||||
if (!z_erofs_is_stagingpage(page)) {
|
||||
#ifdef EROFS_FS_HAS_MANAGED_CACHE
|
||||
if (page->mapping == mngda) {
|
||||
DBG_BUGON(!PageUptodate(page));
|
||||
continue;
|
||||
}
|
||||
if (page->mapping == mngda) {
|
||||
if (unlikely(!PageUptodate(page)))
|
||||
err = -EIO;
|
||||
continue;
|
||||
}
|
||||
#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(pages[pagenr]);
|
||||
++sparsemem_pages;
|
||||
pages[pagenr] = page;
|
||||
DBG_BUGON(pagenr >= nr_pages);
|
||||
DBG_BUGON(pages[pagenr]);
|
||||
++sparsemem_pages;
|
||||
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;
|
||||
|
||||
if (z_erofs_vle_workgrp_fmt(grp) == Z_EROFS_VLE_WORKGRP_FMT_PLAIN) {
|
||||
@@ -1082,6 +1096,8 @@ static inline bool recover_managed_page(struct z_erofs_vle_workgroup *grp,
|
||||
return true;
|
||||
|
||||
lock_page(page);
|
||||
ClearPageError(page);
|
||||
|
||||
if (unlikely(!PagePrivate(page))) {
|
||||
set_page_private(page, (unsigned long)grp);
|
||||
SetPagePrivate(page);
|
||||
|
||||
Reference in New Issue
Block a user