Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Jul 2003 12:33:28 +1000
From:      Tim Robbins <tjr@FreeBSD.ORG>
To:        "Karel J. Bosschaart" <K.J.Bosschaart@tue.nl>
Cc:        current@freebsd.org
Subject:   Re: panic while reading ntfs partition
Message-ID:  <20030725023328.GA5294@dilbert.robbins.dropbear.id.au>
In-Reply-To: <20030724121420.GA1055@phys9911.phys.tue.nl>
References:  <20030724121420.GA1055@phys9911.phys.tue.nl>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Jul 24, 2003 at 02:14:20PM +0200, Karel J. Bosschaart wrote:

> Not sure if this is useful, but I'm getting a perfectly reproducible
> panic when doing 'grep -R foo .' (as normal user) in a read-only
> mounted ntfs partition on a -current as of ~3 weeks ago:
> 
[...]
>   Panicstring: bundirty: buffer 0xc72d9868 still on queue 2
[...]

Thanks for the report - I thought I'd already fixed this problem. Would you
mind trying the attached patch? It seems to fix the problem for me, but
grep uses an awful lot of memory in the process (perhaps it's trying to
read a "line" from the pagefile containing mostly zeroes.)

See these two for more info on the bug:
http://perforce.freebsd.org/chv.cgi?CH=34967
http://perforce.freebsd.org/chv.cgi?CH=33434


diff -ru sys/fs/ntfs.old/ntfs_subr.c sys/fs/ntfs/ntfs_subr.c
--- sys/fs/ntfs.old/ntfs_subr.c	Fri Jul 25 12:26:18 2003
+++ sys/fs/ntfs/ntfs_subr.c	Fri Jul 25 12:18:09 2003
@@ -1442,9 +1442,16 @@
 		off = ntfs_btocnoff(off);
 
 		while (left && ccl) {
-			tocopy = min(left,
-				  min(ntfs_cntob(ccl) - off, MAXBSIZE - off));
+			/*
+			 * Always read and write single clusters at a time -
+			 * we need to avoid requesting differently-sized
+			 * blocks at the same disk offsets to avoid
+			 * confusing the buffer cache.
+			 */
+			tocopy = min(left, ntfs_cntob(1) - off);
 			cl = ntfs_btocl(tocopy + off);
+			KASSERT(cl == 1 && tocopy <= ntfs_cntob(1),
+			    ("single cluster limit mistake"));
 			ddprintf(("ntfs_writentvattr_plain: write: " \
 				"cn: 0x%x cl: %d, off: %d len: %d, left: %d\n",
 				(u_int32_t) cn, (u_int32_t) cl, 
@@ -1540,23 +1547,19 @@
 				off = ntfs_btocnoff(off);
 
 				while (left && ccl) {
-					tocopy = min(left,
-						  min(ntfs_cntob(ccl) - off,
-						      MAXBSIZE - off));
-					cl = ntfs_btocl(tocopy + off);
-
 					/*
-					 * If 'off' pushes us to next
-					 * block, don't attempt to read whole
-					 * 'tocopy' at once. This is to avoid
-					 * bread() with varying 'size' for
-					 * same 'blkno', which is not good.
+					 * Always read single clusters at a
+					 * time - we need to avoid reading
+					 * differently-sized blocks at the
+					 * same disk offsets to avoid
+					 * confusing the buffer cache.
 					 */
-					if (cl > ntfs_btocl(tocopy)) {
-						tocopy -=
-						    ntfs_btocnoff(tocopy + off);
-						cl--;
-					}
+					tocopy = min(left,
+					    ntfs_cntob(1) - off);
+					cl = ntfs_btocl(tocopy + off);
+					KASSERT(cl == 1 &&
+					    tocopy <= ntfs_cntob(1),
+					    ("single cluster limit mistake"));
 
 					ddprintf(("ntfs_readntvattr_plain: " \
 						"read: cn: 0x%x cl: %d, " \
diff -ru sys/fs/ntfs.old/ntfs_vfsops.c sys/fs/ntfs/ntfs_vfsops.c
--- sys/fs/ntfs.old/ntfs_vfsops.c	Fri Jul 25 12:26:18 2003
+++ sys/fs/ntfs/ntfs_vfsops.c	Fri Jul 25 12:18:09 2003
@@ -311,6 +311,14 @@
 		goto out;
 	ntmp = malloc( sizeof *ntmp, M_NTFSMNT, M_WAITOK | M_ZERO);
 	bcopy( bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile) );
+	/*
+	 * We must not cache the boot block if its size is not exactly
+	 * one cluster in order to avoid confusing the buffer cache when
+	 * the boot file is read later by ntfs_readntvattr_plain(), which
+	 * reads a cluster at a time.
+	 */
+	if (ntfs_cntob(1) != BBSIZE)
+		bp->b_flags |= B_NOCACHE;
 	brelse( bp );
 	bp = NULL;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030725023328.GA5294>