From 1bd12a3bb2be72a7d360402f489000dd337f6f3b Mon Sep 17 00:00:00 2001 From: Chuck Silvers Date: Fri, 17 Jul 2020 23:10:35 +0000 Subject: [PATCH] Fix vnode_pager handling of read ahead/behind pages when a disk read fails. Rather than marking the read ahead/behind pages valid even though they were not initialized, free them using the new function vm_page_free_invalid(). Reviewed by: markj, kib Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D25430 --- sys/vm/vnode_pager.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 0f3ea7300654..fa9f4cab16f9 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -1139,6 +1139,21 @@ vnode_pager_generic_getpages_done(struct buf *bp) bp->b_data = unmapped_buf; } + /* + * If the read failed, we must free any read ahead/behind pages here. + * The requested pages are freed by the caller (for sync requests) + * or by the bp->b_pgiodone callback (for async requests). + */ + if (error != 0) { + VM_OBJECT_WLOCK(object); + for (i = 0; i < bp->b_pgbefore; i++) + vm_page_free_invalid(bp->b_pages[i]); + for (i = bp->b_npages - bp->b_pgafter; i < bp->b_npages; i++) + vm_page_free_invalid(bp->b_pages[i]); + VM_OBJECT_WUNLOCK(object); + return (error); + } + /* Read lock to protect size. */ VM_OBJECT_RLOCK(object); for (i = 0, tfoff = IDX_TO_OFF(bp->b_pages[0]->pindex);