kern/56675: Syncer "giving up" on buffers and ext2 filesystems
[still a problem in 5.3RC1]
Don Lewis
truckman at FreeBSD.org
Tue Sep 6 17:58:22 PDT 2005
Synopsis: Syncer "giving up" on buffers and ext2 filesystems [still a problem in 5.3RC1]
State-Changed-From-To: open->feedback
State-Changed-By: truckman
State-Changed-When: Wed Sep 7 00:56:49 GMT 2005
State-Changed-Why:
The following patch was sent to the PR submitter for testing:
Index: sys/kern/kern_shutdown.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_shutdown.c,v
retrieving revision 1.163.2.4
diff -u -r1.163.2.4 kern_shutdown.c
--- sys/kern/kern_shutdown.c 7 Jan 2005 20:09:08 -0000 1.163.2.4
+++ sys/kern/kern_shutdown.c 6 Sep 2005 03:28:00 -0000
@@ -249,6 +249,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.
*/
@@ -304,16 +314,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("No buffers busy after final sync");
@@ -359,8 +362,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 (bp->b_dev == NULL) {
TAILQ_REMOVE(&mountlist,
bp->b_vp->v_mount, mnt_list);
Index: sys/kern/vfs_bio.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v
retrieving revision 1.444.2.3
diff -u -r1.444.2.3 vfs_bio.c
--- sys/kern/vfs_bio.c 26 Jun 2005 23:55:50 -0000 1.444.2.3
+++ sys/kern/vfs_bio.c 6 Sep 2005 03:24:06 -0000
@@ -1466,7 +1466,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.167.2.3
diff -u -r1.167.2.3 buf.h
--- sys/sys/buf.h 16 Aug 2005 15:09:44 -0000 1.167.2.3
+++ sys/sys/buf.h 6 Sep 2005 03:34:06 -0000
@@ -205,7 +205,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. */
@@ -232,8 +232,8 @@
#define PRINT_BUF_FLAGS "\20\40b31\37cluster\36vmio\35ram\34b27" \
"\33paging\32b25\31writeinprog\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\11persistent\10delwri\7validsuspwrt" \
"\6cache\5deferred\4direct\3async\2needcommit\1age"
/*
Index: sys/gnu/ext2fs/fs.h
===================================================================
RCS file: /home/ncvs/src/sys/gnu/ext2fs/Attic/fs.h,v
retrieving revision 1.16.2.1
diff -u -r1.16.2.1 fs.h
--- sys/gnu/ext2fs/fs.h 31 Jan 2005 23:26:02 -0000 1.16.2.1
+++ sys/gnu/ext2fs/fs.h 6 Sep 2005 03:25:01 -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; \
Responsible-Changed-From-To: freebsd-bugs->truckman
Responsible-Changed-By: truckman
Responsible-Changed-When: Wed Sep 7 00:56:49 GMT 2005
Responsible-Changed-Why:
http://www.freebsd.org/cgi/query-pr.cgi?pr=56675
More information about the freebsd-bugs
mailing list