Add a new struct buf flag bit, B_PERSISTENT, and use it to tag
struct bufs that are persistently held by ext2fs. Ignore any buffers with this flag in the code in boot() that counts "busy" and dirty buffers and attempts to sync the dirty buffers, which is done before attempting to unmount all the file systems during shutdown. This fixes the problem caused by any ext2fs file systems that are mounted at system shutdown time, which caused boot() to give up on a non-zero number of buffers and skip the call to vfs_unmountall(). This left all the mounted file systems in a dirty state and caused them to all require cleanup by fsck on reboot. Move the two separate copies of the "busy" buffer test in boot() to a separate function. Nuke the useless spl() stuff in the ext2fs ULCK_BUF() macro. Bring the PRINT_BUF_FLAGS definition in sys/buf.h up to date with this and previous flag changes. PR: kern/56675, kern/85163 Tested by: "Matthias Andree" matthias.andree at gmx.de Reviewed by: bde MFC after: 3 days
This commit is contained in:
parent
ba217ebb58
commit
d07f87a218
@ -150,19 +150,19 @@ extern u_char *fragtbl[];
|
||||
|
||||
/*
|
||||
* Historically, ext2fs kept it's metadata buffers on the LOCKED queue. Now,
|
||||
* we simply change the lock owner to kern so that it may be released from
|
||||
* another context. Later, we release the buffer, and conditionally write it
|
||||
* when we're done.
|
||||
* we change the lock owner to kern so that we may use it from contexts other
|
||||
* than the one that originally locked it. When we are finished with the
|
||||
* buffer, we release it, writing it first if it was dirty.
|
||||
*/
|
||||
#define LCK_BUF(bp) BUF_KERNPROC(bp);
|
||||
#define LCK_BUF(bp) { \
|
||||
(bp)->b_flags |= B_PERSISTENT; \
|
||||
BUF_KERNPROC(bp); \
|
||||
}
|
||||
|
||||
#define ULCK_BUF(bp) { \
|
||||
long flags; \
|
||||
int s; \
|
||||
s = splbio(); \
|
||||
flags = (bp)->b_flags; \
|
||||
(bp)->b_flags &= ~(B_DIRTY); \
|
||||
splx(s); \
|
||||
(bp)->b_flags &= ~(B_DIRTY | B_PERSISTENT); \
|
||||
if (flags & B_DIRTY) \
|
||||
bwrite(bp); \
|
||||
else \
|
||||
|
@ -236,6 +236,16 @@ doadump(void)
|
||||
dumpsys(&dumper);
|
||||
}
|
||||
|
||||
static int
|
||||
isbufbusy(struct buf *bp)
|
||||
{
|
||||
if (((bp->b_flags & (B_INVAL | B_PERSISTENT)) == 0 &&
|
||||
BUF_REFCNT(bp) > 0) ||
|
||||
((bp->b_flags & (B_DELWRI | B_INVAL)) == B_DELWRI))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown the system cleanly to prepare for reboot, halt, or power off.
|
||||
*/
|
||||
@ -288,16 +298,9 @@ boot(int howto)
|
||||
*/
|
||||
for (iter = pbusy = 0; iter < 20; iter++) {
|
||||
nbusy = 0;
|
||||
for (bp = &buf[nbuf]; --bp >= buf; ) {
|
||||
if ((bp->b_flags & B_INVAL) == 0 &&
|
||||
BUF_REFCNT(bp) > 0) {
|
||||
for (bp = &buf[nbuf]; --bp >= buf; )
|
||||
if (isbufbusy(bp))
|
||||
nbusy++;
|
||||
} else if ((bp->b_flags & (B_DELWRI | B_INVAL))
|
||||
== B_DELWRI) {
|
||||
/* bawrite(bp);*/
|
||||
nbusy++;
|
||||
}
|
||||
}
|
||||
if (nbusy == 0) {
|
||||
if (first_buf_printf)
|
||||
printf("All buffers synced.");
|
||||
@ -343,8 +346,7 @@ boot(int howto)
|
||||
*/
|
||||
nbusy = 0;
|
||||
for (bp = &buf[nbuf]; --bp >= buf; ) {
|
||||
if (((bp->b_flags&B_INVAL) == 0 && BUF_REFCNT(bp)) ||
|
||||
((bp->b_flags & (B_DELWRI|B_INVAL)) == B_DELWRI)) {
|
||||
if (isbufbusy(bp)) {
|
||||
#if 0
|
||||
/* XXX: This is bogus. We should probably have a BO_REMOTE flag instead */
|
||||
if (bp->b_dev == NULL) {
|
||||
|
@ -195,7 +195,7 @@ struct buf {
|
||||
#define B_CACHE 0x00000020 /* Bread found us in the cache. */
|
||||
#define B_VALIDSUSPWRT 0x00000040 /* Valid write during suspension. */
|
||||
#define B_DELWRI 0x00000080 /* Delay I/O until buffer reused. */
|
||||
#define B_00000100 0x00000100 /* Available flag. */
|
||||
#define B_PERSISTENT 0x00000100 /* Perm. ref'ed while EXT2FS mounted. */
|
||||
#define B_DONE 0x00000200 /* I/O completed. */
|
||||
#define B_EINTR 0x00000400 /* I/O was interrupted */
|
||||
#define B_00000800 0x00000800 /* Available flag. */
|
||||
@ -220,10 +220,10 @@ struct buf {
|
||||
#define B_CLUSTER 0x40000000 /* pagein op, so swap() can count it */
|
||||
#define B_REMFREE 0x80000000 /* Delayed bremfree */
|
||||
|
||||
#define PRINT_BUF_FLAGS "\20\40b31\37cluster\36vmio\35ram\34b27" \
|
||||
#define PRINT_BUF_FLAGS "\20\40remfree\37cluster\36vmio\35ram\34b27" \
|
||||
"\33paging\32b25\31b24\30b23\27relbuf\26dirty\25b20" \
|
||||
"\24b19\23phys\22clusterok\21malloc\20nocache\17locked\16inval" \
|
||||
"\15scanned\14nowdrain\13eintr\12done\11b8\10delwri\7validsuspwrt" \
|
||||
"\24b19\23b18\22clusterok\21malloc\20nocache\17b14\16inval" \
|
||||
"\15b12\14b11\13eintr\12done\11persist\10delwri\7validsuspwrt" \
|
||||
"\6cache\5deferred\4direct\3async\2needcommit\1age"
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user