Attached below is a patch to fix the problem caused by having any ext2fs file systems mounted at system shutdown time that prevents any of the file systems from being unmounted and then being marked dirty when the system comes back up. It works by tweaking ext2fs so that it marks the bufs that it keeps locked as long as the file system is mounted, and tweaks the shutdown code to ignore these bufs when it is counting the number of busy buffers. This patch applies cleanly to both HEAD and RELENG_6. I rarely use ext2fs and was only able to do runtime testing of this patch on HEAD. I've done compile tests on RELENG_6. I've also got a version of this patch for RELENG_5 that I'll release for testing after I do the commit to HEAD. If you use ext2fs with HEAD or RELENG_6, I'd appreciate it if you could test this patch before I commit it. If possible, I'd like to get this into 6.0-RELEASE. Index: sys/kern/kern_shutdown.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_shutdown.c,v retrieving revision 1.174 diff -u -r1.174 kern_shutdown.c --- sys/kern/kern_shutdown.c 12 Apr 2005 05:45:58 -0000 1.174 +++ sys/kern/kern_shutdown.c 5 Sep 2005 19:21:38 -0000 _at__at_ -236,6 +236,16 _at__at_ 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. */ _at__at_ -288,16 +298,9 _at__at_ */ 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."); _at__at_ -343,8 +346,7 _at__at_ */ 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) { Index: sys/kern/vfs_bio.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v retrieving revision 1.493 diff -u -r1.493 vfs_bio.c --- sys/kern/vfs_bio.c 3 Aug 2005 05:02:08 -0000 1.493 +++ sys/kern/vfs_bio.c 5 Sep 2005 07:46:49 -0000 _at__at_ -1365,7 +1365,8 _at__at_ if (bp->b_bufsize || bp->b_kvasize) bufspacewakeup(); - bp->b_flags &= ~(B_ASYNC | B_NOCACHE | B_AGE | B_RELBUF | B_DIRECT); + bp->b_flags &= ~(B_ASYNC | B_NOCACHE | B_AGE | B_RELBUF | B_DIRECT | + B_PERSISTENT); if ((bp->b_flags & B_DELWRI) == 0 && (bp->b_xflags & BX_VNDIRTY)) panic("brelse: not dirty"); /* unlock */ Index: sys/sys/buf.h =================================================================== RCS file: /home/ncvs/src/sys/sys/buf.h,v retrieving revision 1.188 diff -u -r1.188 buf.h --- sys/sys/buf.h 13 Aug 2005 20:21:33 -0000 1.188 +++ sys/sys/buf.h 5 Sep 2005 19:36:24 -0000 _at__at_ -195,7 +195,7 _at__at_ #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 fs mounted. */ #define B_DONE 0x00000200 /* I/O completed. */ #define B_EINTR 0x00000400 /* I/O was interrupted */ #define B_00000800 0x00000800 /* Available flag. */ _at__at_ -220,10 +220,10 _at__at_ #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" /* Index: sys/gnu/fs/ext2fs/fs.h =================================================================== RCS file: /home/ncvs/src/sys/gnu/fs/ext2fs/fs.h,v retrieving revision 1.17 diff -u -r1.17 fs.h --- sys/gnu/fs/ext2fs/fs.h 6 Jan 2005 18:27:30 -0000 1.17 +++ sys/gnu/fs/ext2fs/fs.h 5 Sep 2005 21:29:11 -0000 _at__at_ -150,11 +150,16 _at__at_ /* * 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 simply 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. The + * B_PERSISTENT flag is cleared by brelse(), which bwrite() calls after the + * buffer is written in the B_DIRTY case. */ -#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; \Received on Tue Sep 06 2005 - 05:39:37 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:42 UTC