On Fri, Nov 06, 2020 at 09:37:46AM +0100, Christoph Hellwig wrote: > > - error = AOP_TRUNCATED_PAGE; > - if (!page->mapping) > - goto unlock; > - if (filemap_range_uptodate(iocb, mapping, iter, page)) { > + if (!page->mapping) { > unlock_page(page); > - return 0; > + put_page(page); > + return AOP_TRUNCATED_PAGE; > } > > - error = -EAGAIN; > - if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT | IOCB_WAITQ)) > - goto unlock; > + if (!filemap_range_uptodate(iocb, mapping, iter, page)) { > + error = -EAGAIN; > + if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT | IOCB_WAITQ)) > + goto unlock; > + return filemap_read_page(iocb->ki_filp, mapping, page); > + } > > - error = filemap_read_page(iocb->ki_filp, mapping, page); > - if (error) > - goto error; > - return 0; > unlock: > unlock_page(page); > -error: > - put_page(page); > return error; > } It works out to be a little more complicated than that because filemap_read_page() can also return AOP_TRUNCATED_PAGE. Here's what I currently have: if (!page->mapping) goto truncated; error = 0; if (filemap_range_uptodate(iocb, mapping, iter, page)) goto unlock; error = -EAGAIN; if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT | IOCB_WAITQ)) goto unlock; error = filemap_read_page(iocb->ki_filp, mapping, page); if (error == AOP_TRUNCATED_PAGE) put_page(page); return error; truncated: error = AOP_TRUNCATED_PAGE; put_page(page); unlock: unlock_page(page); return error; }