Subject: Re: uvm_fp2 deadlock in 1.6B4
To: tld <tld@tld.digitalcurse.com>
From: Jaromir Dolecek <jdolecek@netbsd.org>
List: current-users
Date: 08/07/2002 20:09:13
--ELM72957166-1291-0_
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=US-ASCII

tld wrote:
> So far it happened 3 times (out of 3 tries to backup the drives), and 
> only on ext2fs partitions. Similar problems did not arise with ffs 
> (softdep off) when doing the very same things.

Cool. This is important - it's likely a ext2fs bug then.

> As for the DDB, I can compile that, find a keyboard and a monitor (I 
> can't do that via network, can I?).
> I don't know about "provide kernel traceback of gzip process". If given 
> appropriate instructions I will gladly follow them and provide with 
> anything you might need.

Hmm, let's try something a simple change first.

I noted some difference between ext2fs_balloc_range() and
ufs_balloc_range(). There doesn't seem to be particular reason for
this difference, and basically doesn't seem to be particular reason
for ext2fs-specific function at all.

Can you try appended patch, which makes ext2fs code to use the
ufs_balloc_range() function, rather than it's own, slightly incorrect,
copy? The patch should be applied in sys/ufs/ext2fs/ directory.

Note this patch isn't really tested, so be careful (and keep old
kernel around ;)

Jaromir
-- 
Jaromir Dolecek <jdolecek@NetBSD.org>            http://www.NetBSD.org/
-=- We should be mindful of the potential goal, but as the tantric    -=-
-=- Buddhist masters say, ``You may notice during meditation that you -=-
-=- sometimes levitate or glow.   Do not let this distract you.''     -=-

--ELM72957166-1291-0_
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=ISO-8859-2
Content-Disposition: attachment; filename=e2fix.diff

? e2fix.diff
Index: ext2fs_balloc.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ext2fs/ext2fs_balloc.c,v
retrieving revision 1.17
diff -u -p -r1.17 ext2fs_balloc.c
--- ext2fs_balloc.c	2002/05/05 17:01:41	1.17
+++ ext2fs_balloc.c	2002/08/07 18:03:05
@@ -368,97 +368,3 @@ ext2fs_gop_alloc(struct vnode *vp, off_t
 	}
 	return 0;
 }
-
-/*
- * allocate a range of blocks in a file.
- * after this function returns, any page entirely contained within the range
- * will map to invalid data and thus must be overwritten before it is made
- * accessible to others.
- */
-
-int
-ext2fs_balloc_range(vp, off, len, cred, flags)
-	struct vnode *vp;
-	off_t off, len;
-	struct ucred *cred;
-	int flags;
-{
-	off_t oldeof, eof, pagestart;
-	struct genfs_node *gp = VTOG(vp);
-	int i, delta, error, npages;
-	int bshift = vp->v_mount->mnt_fs_bshift;
-	int bsize = 1 << bshift;
-	int ppb = max(bsize >> PAGE_SHIFT, 1);
-	struct vm_page *pgs[ppb];
-	UVMHIST_FUNC("ext2fs_balloc_range"); UVMHIST_CALLED(ubchist);
-	UVMHIST_LOG(ubchist, "vp %p off 0x%x len 0x%x u_size 0x%x",
-		    vp, off, len, vp->v_size);
-
-	oldeof = vp->v_size;
-	eof = MAX(oldeof, off + len);
-	UVMHIST_LOG(ubchist, "new eof 0x%x", eof,0,0,0);
-	pgs[0] = NULL;
-
-	/*
-	 * cache the new range of the file.  this will create zeroed pages
-	 * where the new block will be and keep them locked until the
-	 * new block is allocated, so there will be no window where
-	 * the old contents of the new block is visible to racing threads.
-	 */
-
-	pagestart = trunc_page(off) & ~(bsize - 1);
-	npages = MIN(ppb, (round_page(eof) - pagestart) >> PAGE_SHIFT);
-	memset(pgs, 0, npages * sizeof(struct vm_page *));
-	simple_lock(&vp->v_interlock);
-	error = VOP_GETPAGES(vp, pagestart, pgs, &npages, 0,
-	    VM_PROT_READ, 0, PGO_SYNCIO | PGO_PASTEOF);
-	if (error) {
-		return error;
-	}
-	for (i = 0; i < npages; i++) {
-		UVMHIST_LOG(ubchist, "got pgs[%d] %p", i, pgs[i],0,0);
-		KASSERT((pgs[i]->flags & PG_RELEASED) == 0);
-		pgs[i]->flags &= ~PG_CLEAN;
-		uvm_pageactivate(pgs[i]);
-	}
-
-	/*
-	 * adjust off to be block-aligned.
-	 */
-
-	delta = off & (bsize - 1);
-	off -= delta;
-	len += delta;
-
-	/*
-	 * now allocate the range.
-	 */
-
-	lockmgr(&gp->g_glock, LK_EXCLUSIVE, NULL);
-	error = GOP_ALLOC(vp, off, len, flags, cred);
-	UVMHIST_LOG(ubchist, "alloc %d", error,0,0,0);
-	lockmgr(&gp->g_glock, LK_RELEASE, NULL);
-
-	/*
-	 * clear PG_RDONLY on any pages we are holding
-	 * (since they now have backing store) and unbusy them.
-	 * if we got an error, free any pages we created past the old eob.
-	 */
-
-	simple_lock(&vp->v_interlock);
-	for (i = 0; i < npages; i++) {
-		pgs[i]->flags &= ~PG_RDONLY;
-		if (error) {
-			pgs[i]->flags |= PG_RELEASED;
-		}
-	}
-	if (error) {
-		uvm_lock_pageq();
-		uvm_page_unbusy(pgs, npages);
-		uvm_unlock_pageq();
-	} else {
-		uvm_page_unbusy(pgs, npages);
-	}
-	simple_unlock(&vp->v_interlock);
-	return (error);
-}
Index: ext2fs_extern.h
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ext2fs/ext2fs_extern.h,v
retrieving revision 1.11
diff -u -p -r1.11 ext2fs_extern.h
--- ext2fs_extern.h	2001/09/15 20:36:41	1.11
+++ ext2fs_extern.h	2002/08/07 18:03:05
@@ -72,8 +72,6 @@ int ext2fs_vfree __P((void *));
 int ext2fs_balloc __P((struct inode *, ufs_daddr_t, int, struct ucred *,
 			struct buf **, int));
 int ext2fs_gop_alloc __P((struct vnode *, off_t, off_t, int, struct ucred *));
-int ext2fs_balloc_range __P((struct vnode *, off_t, off_t, struct ucred *,
-			     int));
 
 /* ext2fs_bmap.c */
 int ext2fs_bmap __P((void *));
Index: ext2fs_inode.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ext2fs/ext2fs_inode.c,v
retrieving revision 1.27
diff -u -p -r1.27 ext2fs_inode.c
--- ext2fs_inode.c	2001/11/08 02:39:07	1.27
+++ ext2fs_inode.c	2002/08/07 18:03:05
@@ -236,7 +236,7 @@ ext2fs_truncate(v)
 		if (length > fs->fs_maxfilesize)
 			return (EFBIG);
 #endif
-		ext2fs_balloc_range(ovp, length - 1, 1, ap->a_cred,
+		ufs_balloc_range(ovp, length - 1, 1, ap->a_cred,
 		    ap->a_flags & IO_SYNC ? B_SYNC : 0);
 		oip->i_flag |= IN_CHANGE | IN_UPDATE;
 		return (VOP_UPDATE(ovp, NULL, NULL, 1));
Index: ext2fs_readwrite.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ext2fs/ext2fs_readwrite.c,v
retrieving revision 1.24
diff -u -p -r1.24 ext2fs_readwrite.c
--- ext2fs_readwrite.c	2002/03/25 02:23:55	1.24
+++ ext2fs_readwrite.c	2002/08/07 18:03:05
@@ -55,6 +55,7 @@ __KERNEL_RCSID(0, "$NetBSD: ext2fs_readw
 #include <sys/signalvar.h>
 
 #include <ufs/ufs/inode.h>
+#include <ufs/ufs/ufs_extern.h>
 #include <ufs/ext2fs/ext2fs.h>
 #include <ufs/ext2fs/ext2fs_extern.h>
 
@@ -272,7 +273,7 @@ ext2fs_write(v)
 			bytelen = MIN(fs->e2fs_bsize - blkoffset,
 			    uio->uio_resid);
 
-			error = ext2fs_balloc_range(vp, uio->uio_offset,
+			error = ufs_balloc_range(vp, uio->uio_offset,
 			    bytelen, ap->a_cred, 0);
 			if (error) {
 				break;

--ELM72957166-1291-0_--