git: 2a27aefcefe0 - stable/15 - swap_pager_getpages(): some pages from ma[] might be bogus
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 24 Jan 2026 00:32:32 UTC
The branch stable/15 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=2a27aefcefe05fb531189b256bad63c3c8f5cea5
commit 2a27aefcefe05fb531189b256bad63c3c8f5cea5
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-01-13 13:35:28 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-01-24 00:26:45 +0000
swap_pager_getpages(): some pages from ma[] might be bogus
(cherry picked from commit d198ad51ea73bbb162336923a387f52b0b1c1f1d)
---
sys/vm/swap_pager.c | 37 +++++++++++++++++++++++++++++--------
1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 012d89db3310..f6d201309349 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -1362,14 +1362,22 @@ static int
swap_pager_getpages_locked(struct pctrie_iter *blks, vm_object_t object,
vm_page_t *ma, int count, int *a_rbehind, int *a_rahead, struct buf *bp)
{
+ vm_page_t m;
vm_pindex_t pindex;
- int rahead, rbehind;
+ int i, rahead, rbehind;
VM_OBJECT_ASSERT_WLOCKED(object);
KASSERT((object->flags & OBJ_SWAP) != 0,
("%s: object not swappable", __func__));
- pindex = ma[0]->pindex;
+ for (i = 0; i < count; i++) {
+ m = ma[i];
+ if (m != bogus_page) {
+ pindex = m->pindex - i;
+ break;
+ }
+ }
+ MPASS(i != count);
if (!swp_pager_haspage_iter(pindex, &rbehind, &rahead, blks)) {
VM_OBJECT_WUNLOCK(object);
uma_zfree(swrbuf_zone, bp);
@@ -1399,8 +1407,11 @@ swap_pager_getpages_locked(struct pctrie_iter *blks, vm_object_t object,
KASSERT(bp->b_npages <= PBUF_PAGES,
("bp_npages %d (rb %d c %d ra %d) not less than PBUF_PAGES %jd",
bp->b_npages, rbehind, count, rahead, (uintmax_t)PBUF_PAGES));
- for (int i = 0; i < bp->b_npages; i++)
- bp->b_pages[i]->oflags |= VPO_SWAPINPROG;
+ for (i = 0; i < bp->b_npages; i++) {
+ m = bp->b_pages[i];
+ if (m != bogus_page)
+ m->oflags |= VPO_SWAPINPROG;
+ }
bp->b_blkno = swp_pager_meta_lookup(blks, pindex - rbehind);
KASSERT(bp->b_blkno != SWAPBLK_NONE,
("no swap blocking containing %p(%jx)", object, (uintmax_t)pindex));
@@ -1448,8 +1459,14 @@ swap_pager_getpages_locked(struct pctrie_iter *blks, vm_object_t object,
*/
VM_OBJECT_WLOCK(object);
/* This could be implemented more efficiently with aflags */
- while ((ma[0]->oflags & VPO_SWAPINPROG) != 0) {
- ma[0]->oflags |= VPO_SWAPSLEEP;
+ for (i = 0; i < count; i++) {
+ m = ma[i];
+ if (m != bogus_page)
+ break;
+ }
+ MPASS(i != count);
+ while ((m->oflags & VPO_SWAPINPROG) != 0) {
+ m->oflags |= VPO_SWAPSLEEP;
VM_CNT_INC(v_intrans);
if (VM_OBJECT_SLEEP(object, &object->handle, PSWP,
"swread", hz * 20)) {
@@ -1463,9 +1480,10 @@ swap_pager_getpages_locked(struct pctrie_iter *blks, vm_object_t object,
/*
* If we had an unrecoverable read error pages will not be valid.
*/
- for (int i = 0; i < count; i++)
- if (ma[i]->valid != VM_PAGE_BITS_ALL)
+ for (i = 0; i < count; i++) {
+ if (ma[i] != bogus_page && ma[i]->valid != VM_PAGE_BITS_ALL)
return (VM_PAGER_ERROR);
+ }
return (VM_PAGER_OK);
@@ -1730,6 +1748,9 @@ swp_pager_async_iodone(struct buf *bp)
for (i = 0; i < bp->b_npages; ++i) {
vm_page_t m = bp->b_pages[i];
+ if (m == bogus_page)
+ continue;
+
m->oflags &= ~VPO_SWAPINPROG;
if (m->oflags & VPO_SWAPSLEEP) {
m->oflags &= ~VPO_SWAPSLEEP;