From: Martin Pieuchot Subject: Re: bufbackoff() & freed pages To: tech@openbsd.org Date: Tue, 5 Nov 2024 17:24:03 +0100 On 02/11/24(Sat) 13:01, Martin Pieuchot wrote: > On 20/10/24(Sun) 11:33, Martin Pieuchot wrote: > > This changes bufbackoff() to return the amount of recovered pages. > > I'll be using this soon to access `uvmexp.free' only once per > > iteration. > > I got a positive review. Any ok? New version with some tweaks from tb@. ok? Index: kern/vfs_bio.c =================================================================== RCS file: /cvs/src/sys/kern/vfs_bio.c,v diff -u -p -r1.213 vfs_bio.c --- kern/vfs_bio.c 3 Feb 2024 18:51:58 -0000 1.213 +++ kern/vfs_bio.c 5 Nov 2024 16:16:57 -0000 @@ -284,22 +284,16 @@ bufadjust(int newbufpages) } /* - * Make the buffer cache back off from cachepct. + * Back off "size" buffer cache pages. Called by the page + * daemon to consume buffer cache pages rather than scanning. + * + * It returns the number of freed pages. */ -int +unsigned long bufbackoff(struct uvm_constraint_range *range, long size) { - /* - * Back off "size" buffer cache pages. Called by the page - * daemon to consume buffer cache pages rather than scanning. - * - * It returns 0 to the pagedaemon to indicate that it has - * succeeded in freeing enough pages. It returns -1 to - * indicate that it could not and the pagedaemon should take - * other measures. - * - */ long pdelta, oldbufpages; + int64_t dmarecovered, recovered = 0; /* * If we will accept high memory for this backoff @@ -307,11 +301,13 @@ bufbackoff(struct uvm_constraint_range * */ if (range != NULL && range->ucr_high > dma_constraint.ucr_high) { struct buf *bp; - int64_t start = bcstats.numbufpages, recovered = 0; - int s = splbio(); + int64_t start; + int s; - while ((recovered < size) && - (bp = bufcache_gethighcleanbuf())) { + start = bcstats.numbufpages; + + s = splbio(); + while (recovered < size && (bp = bufcache_gethighcleanbuf())) { bufcache_take(bp); if (bp->b_vp) { RBT_REMOVE(buf_rb_bufs, @@ -324,16 +320,13 @@ bufbackoff(struct uvm_constraint_range * bufcache_adjust(); splx(s); - /* If we got enough, return success */ + /* We got enough. */ if (recovered >= size) - return 0; + return recovered; - /* - * If we needed only memory above DMA, - * return failure - */ + /* If we needed only memory above DMA, we're done. */ if (range->ucr_low > dma_constraint.ucr_high) - return -1; + return recovered; /* Otherwise get the rest from DMA */ size -= recovered; @@ -351,15 +344,14 @@ bufbackoff(struct uvm_constraint_range * pdelta = (size > bufbackpages) ? size : bufbackpages; if (bufpages <= buflowpages) - return(-1); + return recovered; if (bufpages - pdelta < buflowpages) pdelta = bufpages - buflowpages; oldbufpages = bufpages; bufadjust(bufpages - pdelta); - if (oldbufpages - bufpages < size) - return (-1); /* we did not free what we were asked */ - else - return(0); + dmarecovered = oldbufpages - bufpages; + + return recovered + dmarecovered; } Index: kern/vfs_biomem.c =================================================================== RCS file: /cvs/src/sys/kern/vfs_biomem.c,v diff -u -p -r1.51 vfs_biomem.c --- kern/vfs_biomem.c 24 Oct 2021 00:02:25 -0000 1.51 +++ kern/vfs_biomem.c 5 Nov 2024 16:16:57 -0000 @@ -272,7 +272,7 @@ buf_alloc_pages(struct buf *bp, vsize_t UVM_PLA_NOWAIT | UVM_PLA_NOWAKE); if (i == 0) break; - } while (bufbackoff(&dma_constraint, size) == 0); + } while (bufbackoff(&dma_constraint, size) >= size); if (i != 0) i = uvm_pagealloc_multi(&bp->b_uobj, 0, size, UVM_PLA_WAITOK); @@ -324,6 +324,7 @@ int buf_realloc_pages(struct buf *bp, struct uvm_constraint_range *where, int flags) { + vsize_t size; vaddr_t va; int dma; int i, r; @@ -345,7 +346,8 @@ buf_realloc_pages(struct buf *bp, struct bp->b_bufsize, UVM_PLA_NOWAIT | UVM_PLA_NOWAKE, where); if (r == 0) break; - } while ((bufbackoff(where, atop(bp->b_bufsize)) == 0)); + size = atop(bp->b_bufsize); + } while ((bufbackoff(where, size) >= size)); /* * bufbackoff() failed, so there's no more we can do without Index: uvm/uvm_pdaemon.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_pdaemon.c,v diff -u -p -r1.120 uvm_pdaemon.c --- uvm/uvm_pdaemon.c 5 Nov 2024 15:29:00 -0000 1.120 +++ uvm/uvm_pdaemon.c 5 Nov 2024 16:16:57 -0000 @@ -132,7 +132,7 @@ uvm_wait(const char *wmsg) */ if (curproc == uvm.pagedaemon_proc) { printf("uvm_wait emergency bufbackoff\n"); - if (bufbackoff(NULL, 4) == 0) + if (bufbackoff(NULL, 4) >= 4) return; /* * now we have a problem: the pagedaemon wants to go to Index: uvm/uvm_pmemrange.c =================================================================== RCS file: /cvs/src/sys/uvm/uvm_pmemrange.c,v diff -u -p -r1.68 uvm_pmemrange.c --- uvm/uvm_pmemrange.c 2 Oct 2024 10:17:28 -0000 1.68 +++ uvm/uvm_pmemrange.c 5 Nov 2024 16:16:57 -0000 @@ -2104,7 +2104,7 @@ uvm_wait_pla(paddr_t low, paddr_t high, * easily use up that reserve in a single scan iteration. */ uvm_unlock_fpageq(); - if (bufbackoff(NULL, atop(size)) == 0) { + if (bufbackoff(NULL, atop(size)) >= atop(size)) { uvm_lock_fpageq(); return 0; } Index: sys/mount.h =================================================================== RCS file: /cvs/src/sys/sys/mount.h,v diff -u -p -r1.151 mount.h --- sys/mount.h 3 Feb 2024 18:51:58 -0000 1.151 +++ sys/mount.h 5 Nov 2024 16:16:57 -0000 @@ -495,7 +495,7 @@ extern long buflowpages, bufhighpages, b extern int bufcachepercent; extern void bufadjust(int); struct uvm_constraint_range; -extern int bufbackoff(struct uvm_constraint_range*, long); +extern unsigned long bufbackoff(struct uvm_constraint_range*, long); /* * Operations supported on mounted file system.