diff options
author | msmith <msmith@FreeBSD.org> | 1998-11-13 22:40:37 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 1998-11-13 22:40:37 +0000 |
commit | 0784b75a47132859d84d6e61b79f0eb902bb9988 (patch) | |
tree | 1b442f95af58ff18f9251f047e5dd63dd643bd0d /sys | |
parent | 830a5dfa0cb7ad8afa0574ed21915a1328f8b93f (diff) | |
download | FreeBSD-src-0784b75a47132859d84d6e61b79f0eb902bb9988.zip FreeBSD-src-0784b75a47132859d84d6e61b79f0eb902bb9988.tar.gz |
Don't count non-local dirty buffers as outstanding when shutting down.
This avoids the fsck-on-reboot symptoms if you're shutting down with a
hung or unreachable NFS server mounted. Also remove non-local
filesystems from the mount list to prevent the system hanging when it tries
to unmount them (for the same reason).
Drew points out that there's a good argument for forcibly removing all
"non syncable" filesystems from the mount list (eg. NFS mounts, disks
that aren't responding, etc.) as this then allows you to sync and
cleanly unmount their parents. No such change is included in this
patch.
Submitted by: Andrew Gallatin <gallatin@cs.duke.edu>
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_shutdown.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c index 8a327a2..d2f7116 100644 --- a/sys/kern/kern_shutdown.c +++ b/sys/kern/kern_shutdown.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_shutdown.c 8.3 (Berkeley) 1/21/94 - * $Id: kern_shutdown.c,v 1.40 1998/09/20 16:50:31 dt Exp $ + * $Id: kern_shutdown.c,v 1.41 1998/10/30 05:41:15 msmith Exp $ */ #include "opt_ddb.h" @@ -49,6 +49,7 @@ #include <sys/buf.h> #include <sys/reboot.h> #include <sys/proc.h> +#include <sys/vnode.h> #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/mount.h> @@ -224,6 +225,21 @@ boot(howto) sync(&proc0, NULL); DELAY(50000 * iter); } + /* + * Count only busy local buffers to prevent forcing + * a fsck if we're just a client of a wedged NFS server + */ + nbusy = 0; + for (bp = &buf[nbuf]; --bp >= buf; ) { + if (((bp->b_flags & (B_BUSY | B_INVAL)) == B_BUSY) + ||((bp->b_flags & (B_DELWRI | B_INVAL))== B_DELWRI)) + if(bp->b_dev == NODEV) + CIRCLEQ_REMOVE(&mountlist, bp->b_vp->v_mount, mnt_list); + else + nbusy++; + + + } if (nbusy) { /* * Failed to sync all blocks. Indicate this and don't |