diff options
author | luoqi <luoqi@FreeBSD.org> | 2000-01-07 08:36:44 +0000 |
---|---|---|
committer | luoqi <luoqi@FreeBSD.org> | 2000-01-07 08:36:44 +0000 |
commit | e100d44d5538cc21abeba58f459ce9eb497651a9 (patch) | |
tree | ca8740d97497e39a1d8bb5f7f15e17f85fa4c506 /sys/kern | |
parent | e69b1ea5c9a5104ae1afe7dd26c89222983ed04e (diff) | |
download | FreeBSD-src-e100d44d5538cc21abeba58f459ce9eb497651a9.zip FreeBSD-src-e100d44d5538cc21abeba58f459ce9eb497651a9.tar.gz |
Introduce a mechanism to suspend/resume system processes. Suspend syncer
and bufdaemon prior to disk sync during system shutdown.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_kthread.c | 40 | ||||
-rw-r--r-- | sys/kern/kern_shutdown.c | 32 | ||||
-rw-r--r-- | sys/kern/vfs_bio.c | 31 | ||||
-rw-r--r-- | sys/kern/vfs_export.c | 21 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 21 |
5 files changed, 121 insertions, 24 deletions
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c index b375fbb..5efe90c 100644 --- a/sys/kern/kern_kthread.c +++ b/sys/kern/kern_kthread.c @@ -30,6 +30,7 @@ #include <sys/systm.h> #include <sys/proc.h> #include <sys/kthread.h> +#include <sys/signalvar.h> #include <sys/unistd.h> #include <sys/wait.h> @@ -97,3 +98,42 @@ kthread_exit(int ecode) exit1(curproc, W_EXITCODE(ecode, 0)); } +/* + * Advise a kernel process to suspend (or resume) in its main loop. + * Participation is voluntary. + */ +int +suspend_kproc(struct proc *p, int timo) +{ + /* + * Make sure this is indeed a system process and we can safely + * use the p_siglist field. + */ + if ((p->p_flag & P_SYSTEM) == 0) + return (EINVAL); + SIGADDSET(p->p_siglist, SIGSTOP); + return tsleep((caddr_t)&p->p_siglist, PPAUSE, "suspkp", timo); +} + +int +resume_kproc(struct proc *p) +{ + /* + * Make sure this is indeed a system process and we can safely + * use the p_siglist field. + */ + if ((p->p_flag & P_SYSTEM) == 0) + return (EINVAL); + SIGDELSET(p->p_siglist, SIGSTOP); + wakeup((caddr_t)&p->p_siglist); + return (0); +} + +void +kproc_suspend_loop(struct proc *p) +{ + while (SIGISMEMBER(p->p_siglist, SIGSTOP)) { + wakeup((caddr_t)&p->p_siglist); + tsleep((caddr_t)&p->p_siglist, PPAUSE, "kpsusp", 0); + } +} diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index adf02b6..d66cfbd 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -52,6 +52,7 @@ #include <sys/proc.h> #include <sys/vnode.h> #include <sys/kernel.h> +#include <sys/kthread.h> #include <sys/mount.h> #include <sys/queue.h> #include <sys/sysctl.h> @@ -571,3 +572,34 @@ poweroff_wait(void *junk, int howto) return; DELAY(poweroff_delay * 1000); } + +/* + * Some system processes (e.g. syncer) need to be stopped at appropriate + * points in their main loops prior to a system shutdown, so that they + * won't interfere with the shutdown process (e.g. by holding a disk buf + * to cause sync to fail). For each of these system processes, register + * shutdown_kproc() as a handler for one of shutdown events. + */ +static int kproc_shutdown_wait = 60; +SYSCTL_INT(_kern_shutdown, OID_AUTO, kproc_shutdown_wait, CTLFLAG_RW, + &kproc_shutdown_wait, 0, ""); + +void +shutdown_kproc(void *arg, int howto) +{ + struct proc *p; + int error; + + if (panicstr) + return; + + p = (struct proc *)arg; + printf("Waiting (max %d seconds) for system process `%s' to stop...", + kproc_shutdown_wait * hz, p->p_comm); + error = suspend_kproc(p, kproc_shutdown_wait); + + if (error == EWOULDBLOCK) + printf("timed out\n"); + else + printf("stopped\n"); +} diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index c24a4e0..9d2b5c2 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -29,13 +29,20 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/eventhandler.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mount.h> #include <sys/kernel.h> -#include <sys/sysctl.h> -#include <sys/proc.h> #include <sys/kthread.h> -#include <sys/vnode.h> +#include <sys/proc.h> +#include <sys/reboot.h> +#include <sys/resourcevar.h> +#include <sys/sysctl.h> #include <sys/vmmeter.h> -#include <sys/lock.h> +#include <sys/vnode.h> #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/vm_kern.h> @@ -44,11 +51,6 @@ #include <vm/vm_object.h> #include <vm/vm_extern.h> #include <vm/vm_map.h> -#include <sys/buf.h> -#include <sys/mount.h> -#include <sys/malloc.h> -#include <sys/resourcevar.h> -#include <sys/conf.h> static MALLOC_DEFINE(M_BIOBUF, "BIO buffer", "BIO buffer"); @@ -1666,6 +1668,13 @@ static void buf_daemon() { int s; + + /* + * This process needs to be suspended prior to shutdown sync. + */ + EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_kproc, bufdaemonproc, + SHUTDOWN_PRI_LAST); + /* * This process is allowed to take the buffer cache to the limit */ @@ -1676,7 +1685,9 @@ buf_daemon() bd_flushto = hidirtybuffers; /* dynamically adjusted */ bd_flushinc = 1; - while (TRUE) { + for (;;) { + kproc_suspend_loop(bufdaemonproc); + bd_request = 0; /* diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 059ca2a..f59d819 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -46,20 +46,23 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/dirent.h> +#include <sys/domain.h> +#include <sys/eventhandler.h> #include <sys/fcntl.h> #include <sys/kernel.h> -#include <sys/proc.h> #include <sys/kthread.h> #include <sys/malloc.h> #include <sys/mount.h> +#include <sys/proc.h> +#include <sys/reboot.h> #include <sys/socket.h> -#include <sys/vnode.h> #include <sys/stat.h> -#include <sys/buf.h> -#include <sys/domain.h> -#include <sys/dirent.h> +#include <sys/sysctl.h> #include <sys/vmmeter.h> -#include <sys/conf.h> +#include <sys/vnode.h> #include <machine/limits.h> @@ -72,7 +75,6 @@ #include <vm/vm_pager.h> #include <vm/vnode_pager.h> #include <vm/vm_zone.h> -#include <sys/sysctl.h> static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure"); @@ -975,9 +977,14 @@ sched_sync(void) int s; struct proc *p = updateproc; + EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_kproc, p, + SHUTDOWN_PRI_LAST); + p->p_flag |= P_BUFEXHAUST; for (;;) { + kproc_suspend_loop(p); + starttime = time_second; /* diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 059ca2a..f59d819 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -46,20 +46,23 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/buf.h> +#include <sys/conf.h> +#include <sys/dirent.h> +#include <sys/domain.h> +#include <sys/eventhandler.h> #include <sys/fcntl.h> #include <sys/kernel.h> -#include <sys/proc.h> #include <sys/kthread.h> #include <sys/malloc.h> #include <sys/mount.h> +#include <sys/proc.h> +#include <sys/reboot.h> #include <sys/socket.h> -#include <sys/vnode.h> #include <sys/stat.h> -#include <sys/buf.h> -#include <sys/domain.h> -#include <sys/dirent.h> +#include <sys/sysctl.h> #include <sys/vmmeter.h> -#include <sys/conf.h> +#include <sys/vnode.h> #include <machine/limits.h> @@ -72,7 +75,6 @@ #include <vm/vm_pager.h> #include <vm/vnode_pager.h> #include <vm/vm_zone.h> -#include <sys/sysctl.h> static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure"); @@ -975,9 +977,14 @@ sched_sync(void) int s; struct proc *p = updateproc; + EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_kproc, p, + SHUTDOWN_PRI_LAST); + p->p_flag |= P_BUFEXHAUST; for (;;) { + kproc_suspend_loop(p); + starttime = time_second; /* |