If the filesystem returns an error from get_block, report it instead of ineffectually setting PageError. Don't bother starting any I/Os in this case since they won't bring the page Uptodate. Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx> --- fs/buffer.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 1d5337517dcd..1b0ba1d59966 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2262,7 +2262,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block) sector_t iblock, lblock; struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE]; unsigned int blocksize, bbits; - int nr, i; + int nr, i, err = 0; int fully_mapped = 1; head = create_page_buffers(page, inode, 0); @@ -2280,19 +2280,16 @@ int block_read_full_page(struct page *page, get_block_t *get_block) continue; if (!buffer_mapped(bh)) { - int err = 0; - fully_mapped = 0; if (iblock < lblock) { WARN_ON(bh->b_size != blocksize); err = get_block(inode, iblock, bh, 0); if (err) - SetPageError(page); + break; } if (!buffer_mapped(bh)) { zero_user(page, i * blocksize, blocksize); - if (!err) - set_buffer_uptodate(bh); + set_buffer_uptodate(bh); continue; } /* @@ -2305,18 +2302,17 @@ int block_read_full_page(struct page *page, get_block_t *get_block) arr[nr++] = bh; } while (i++, iblock++, (bh = bh->b_this_page) != head); + if (err) { + unlock_page(page); + return err; + } if (fully_mapped) SetPageMappedToDisk(page); if (!nr) { - /* - * All buffers are uptodate - we can set the page uptodate - * as well. But not if get_block() returned an error. - */ - if (!PageError(page)) - SetPageUptodate(page); - unlock_page(page); - return 0; + /* All buffers are uptodate - we can set the page uptodate */ + SetPageUptodate(page); + return AOP_UPDATED_PAGE; } /* Stage two: lock the buffers */ -- 2.28.0