shithub: riscv

Download patch

ref: 26d36c3ae2fd6ae40148be58589ea5e81b0ca341
parent: 4b2f31131adaec9bd2837d877c4732069db27999
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Jan 22 17:06:42 EST 2019

devswap: simplify, don't panic when writing swapfile fails

always start the pager kproc in swapinit(), simplifying kickpager().

allow zero conf.nswap and conf.nswppo. avoid allocating the reference
map and iolist arrays in that case.

use ulong for ioptr and iolist indices.

don't panic when writing pages out to the swapfile fails. just
requeue the page in the io transaction list so we will try
again next time executeio() is run or just free the page when
the swap reference was dropped.

remove unused pagersummary() function.

--- a/sys/src/9/port/devswap.c
+++ b/sys/src/9/port/devswap.c
@@ -23,7 +23,7 @@
 static AESstate *swapkey;
 
 static Page	**iolist;
-static int	ioptr;
+static ulong	ioptr;
 
 static ushort	ageclock;
 
@@ -30,7 +30,21 @@
 static void
 swapinit(void)
 {
-	swapalloc.swmap = xalloc(conf.nswap);
+	while(conf.nswap && conf.nswppo){
+		swapalloc.swmap = xalloc(conf.nswap);
+		if(swapalloc.swmap == nil)
+			break;
+		iolist = xalloc(conf.nswppo*sizeof(Page*));
+		if(iolist == nil){
+			xfree(swapalloc.swmap);
+			swapalloc.swmap = nil;
+		}
+		break;
+	}
+
+	if(swapalloc.swmap == nil || iolist == nil)
+		conf.nswap = conf.nswppo = 0;
+
 	swapalloc.top = &swapalloc.swmap[conf.nswap];
 	swapalloc.alloc = swapalloc.swmap;
 	swapalloc.last = swapalloc.swmap;
@@ -37,9 +51,7 @@
 	swapalloc.free = conf.nswap;
 	swapalloc.xref = 0;
 
-	iolist = xalloc(conf.nswppo*sizeof(Page*));
-	if(swapalloc.swmap == nil || iolist == nil)
-		panic("swapinit: not enough memory");
+	kproc("pager", pager, 0);
 }
 
 static uintptr
@@ -116,12 +128,7 @@
 void
 kickpager(void)
 {
-	static Ref started;
-
-	if(started.ref || incref(&started) != 1)
-		wakeup(&swapalloc.r);
-	else
-		kproc("pager", pager, 0);
+	wakeup(&swapalloc.r);
 }
 
 static int
@@ -204,7 +211,7 @@
 		}
 		qunlock(&p->seglock);
 
-		if(ioptr > 0) {
+		if(ioptr) {
 			up->psstate = "I/O";
 			executeio();
 		}
@@ -331,28 +338,13 @@
 	}
 }
 
-void
-pagersummary(void)
-{
-	print("%lud/%lud memory %lud/%lud swap %d iolist\n",
-		palloc.user-palloc.freecount,
-		palloc.user, conf.nswap-swapalloc.free, conf.nswap,
-		ioptr);
-}
-
 static void
 executeio(void)
 {
 	Page *outp;
-	int i, n;
-	Chan *c;
-	char *kaddr;
-	KMap *k;
+	ulong i, j;
 
-	c = swapimage.c;
-	for(i = 0; i < ioptr; i++) {
-		if(ioptr > conf.nswppo)
-			panic("executeio: ioptr %d > %d", ioptr, conf.nswppo);
+	for(i = j = 0; i < ioptr; i++) {
 		outp = iolist[i];
 
 		assert(outp->ref > 0);
@@ -361,16 +353,15 @@
 
 		/* only write when swap address still in use */
 		if(swapcount(outp->daddr) > 1){
-			k = kmap(outp);
-			kaddr = (char*)VA(k);
-
-			if(waserror())
-				panic("executeio: page outp I/O error");
-
-			n = devtab[c->type]->write(c, kaddr, BY2PG, outp->daddr);
-			if(n != BY2PG)
-				nexterror();
-
+			Chan *c = swapimage.c;
+			KMap *k = kmap(outp);
+			if(waserror()){
+				kunmap(k);
+				iolist[j++] = outp;
+				continue;
+			}
+			if(devtab[c->type]->write(c, (char*)VA(k), BY2PG, outp->daddr) != BY2PG)
+				error(Eshort);
 			kunmap(k);
 			poperror();
 		}
@@ -381,7 +372,8 @@
 		/* Free up the page after I/O */
 		putpage(outp);
 	}
-	ioptr = 0;
+	ioptr = j;
+	if(j) print("executeio (%lud/%lud): %s\n", j, i, up->errstr);
 }
 
 int
@@ -416,9 +408,9 @@
 		n = devtab[c->type]->stat(c, buf, sizeof buf);
 		if(n <= 0 || convM2D(buf, n, &d, nil) == 0)
 			error("stat failed in setswapchan");
-		if(d.length < conf.nswppo*BY2PG)
+		if(d.length < (vlong)conf.nswppo*BY2PG)
 			error("swap device too small");
-		if(d.length < conf.nswap*BY2PG){
+		if(d.length < (vlong)conf.nswap*BY2PG){
 			conf.nswap = d.length/BY2PG;
 			swapalloc.top = &swapalloc.swmap[conf.nswap];
 			swapalloc.free = conf.nswap;
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -208,7 +208,6 @@
 void		pageinit(void);
 ulong		pagenumber(Page*);
 ulong		pagereclaim(Image*, ulong);
-void		pagersummary(void);
 void		panic(char*, ...);
 Cmdbuf*		parsecmd(char *a, int n);
 void		pathclose(Path*);