Index | Thread | Search

From:
Martin Pieuchot <mpi@grenadille.net>
Subject:
Re: bufbackoff() & freed pages
To:
tech@openbsd.org
Date:
Tue, 5 Nov 2024 17:24:03 +0100

Download raw body.

Thread
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.