From owner-freebsd-current@FreeBSD.ORG Tue Sep 6 07:39:37 2005 Return-Path: X-Original-To: current@FreeBSD.org Delivered-To: freebsd-current@FreeBSD.ORG Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 041B616A41F for ; Tue, 6 Sep 2005 07:39:37 +0000 (GMT) (envelope-from truckman@FreeBSD.org) Received: from gw.catspoiler.org (217-ip-163.nccn.net [209.79.217.163]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9EC9843D45 for ; Tue, 6 Sep 2005 07:39:36 +0000 (GMT) (envelope-from truckman@FreeBSD.org) Received: from FreeBSD.org (mousie.catspoiler.org [192.168.101.2]) by gw.catspoiler.org (8.13.3/8.13.3) with ESMTP id j867dT0x031916 for ; Tue, 6 Sep 2005 00:39:33 -0700 (PDT) (envelope-from truckman@FreeBSD.org) Message-Id: <200509060739.j867dT0x031916@gw.catspoiler.org> Date: Tue, 6 Sep 2005 00:39:29 -0700 (PDT) From: Don Lewis To: current@FreeBSD.org MIME-Version: 1.0 Content-Type: TEXT/plain; charset=us-ascii Cc: Subject: patch for ext2fs unmount problem at shutdown X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 Sep 2005 07:39:37 -0000 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 @@ -236,6 +236,16 @@ 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 @@ */ 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 @@ */ 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 @@ -1365,7 +1365,8 @@ 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 @@ -195,7 +195,7 @@ #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. */ @@ -220,10 +220,10 @@ #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 @@ -150,11 +150,16 @@ /* * 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; \