Subject: can we tsleep() in vfs_shutdown ?
To: None <tech-kern@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 08/03/2000 23:09:00
--VS++wcV0S1rZb1Fb
Content-Type: text/plain; charset=us-ascii

Hi,
in vfs_shutdown(), to pause between flush attemps there is currently a
DELAY(). The problem I can see with this is that we may need some kernel
thread to run for the write to complete (e.g. raidframe, maybe usb ?),
and vfs_shutdown() doesn't give them a chance to have the CPU.
This is supposed to be why system with raid mounted at reboot time don't
always reboot cleanly ("syncing buffers x y z t u giving up").

Is there something that could prevent using tsleep() in vfs_shutdown(),
when we have a valid proc context (that is, not proc0; see attached
patch) ? If I understood it properly we should be in the proc context of the
process which called the reboot syscall, isn't it ?
Of course if we got called from the debugger or panic we're in interrupt
context and already in an emergency situation and we can't pretend to always
work anyway (in case of panic, leaving the kernel thread running may even get
the situation worse).

I have been running this patch on my PC, with a raid-1, array and didn't
notice hill effects, and indeed it fixes the "syncing buffers ... giving up"
problem for me. With my test case (pax -rw of a src tree, src & dst  on the
same raid1 volume) I can have up to 200 dirty buffer at shutdown, and almost
always an unclean shutdown without this change.

--
Manuel Bouyer <bouyer@antioche.eu.org>
--

--VS++wcV0S1rZb1Fb
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

--- vfs_subr.c.orig	Thu Aug  3 22:20:49 2000
+++ vfs_subr.c	Thu Aug  3 22:20:33 2000
@@ -88,6 +88,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
+#include <sys/kernel.h>
 #include <sys/mount.h>
 #include <sys/time.h>
 #include <sys/fcntl.h>
@@ -2399,7 +2400,13 @@
 		if (nbusy == 0)
 			break;
 		printf("%d ", nbusy);
-		DELAY(40000 * iter);
+		if (p != &proc0) {
+			tsleep(&nbusy, PRIBIO, "bflush",
+			    (iter == 0) ? 1 : hz / 25 * iter);
+		} else {
+			printf("has to busy-wait ");
+			DELAY(40000 * iter);
+		}
 	}
 	if (nbusy) {
 fail:

--VS++wcV0S1rZb1Fb--