Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 24 Feb 2000 01:48:14 +0000
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        Matthew Dillon <dillon@apollo.backplane.com>
Cc:        freebsd-current@freebsd.org
Subject:   Re: ffs_blkfree: freeing free block (was Re: Panic (pmap)) 
Message-ID:   <200002240148.aa34053@salmon.maths.tcd.ie>
In-Reply-To: Your message of "Wed, 23 Feb 2000 22:35:29 GMT." <200002232235.aa22335@salmon.maths.tcd.ie> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <200002232235.aa22335@salmon.maths.tcd.ie>, Ian Dowse writes:
>
>The fix should be relatively straightforward - either the code should
>avoid linking new indirection blocks until all allocations succeed,
>or it should back out the changes on failure.

Here's one patch that seems to fix the problem. It may not be the best
approach though?

Ian

--- ffs_balloc.c.orig	Thu Feb 24 00:44:32 2000
+++ ffs_balloc.c	Thu Feb 24 01:45:46 2000
@@ -71,7 +71,7 @@
 	int flags;
 	struct fs *fs;
 	ufs_daddr_t nb;
-	struct buf *bp, *nbp;
+	struct buf *bp, *nbp, *allocbp;
 	struct vnode *vp;
 	struct indir indirs[NIADDR + 2];
 	ufs_daddr_t newb, *bap, pref;
@@ -197,6 +197,7 @@
 	--num;
 	nb = ip->i_ib[indirs[0].in_off];
 	allocib = NULL;
+	allocbp = NULL;
 	allocblk = allociblk;
 	if (nb == 0) {
 		pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
@@ -272,6 +273,17 @@
 			}
 		}
 		bap[indirs[i - 1].in_off] = nb;
+		if (allocib == NULL) {
+			/* 
+			 * Writing bp would link in the newly allocated
+			 * blocks; hold off in case of allocation failure
+			 * later.
+			 */
+			allocib = &bap[indirs[i - 1].in_off];
+			allocbp = bp;
+			continue;
+		}
+
 		/*
 		 * If required, write synchronously, otherwise use
 		 * delayed write.
@@ -316,8 +328,7 @@
 				bp->b_flags |= B_CLUSTEROK;
 			bdwrite(bp);
 		}
-		*ap->a_bpp = nbp;
-		return (0);
+		goto success;
 	}
 	brelse(bp);
 	if (flags & B_CLRBUF) {
@@ -330,6 +341,22 @@
 		nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0);
 		nbp->b_blkno = fsbtodb(fs, nb);
 	}
+success:
+	if (allocbp != NULL) {
+		/*
+		 * It is safe to write allocbp now.
+		 *
+		 * If required, write synchronously, otherwise use
+		 * delayed write.
+		 */
+		if (flags & B_SYNC) {
+			bwrite(allocbp);
+		} else {
+			if (allocbp->b_bufsize == fs->fs_bsize)
+				allocbp->b_flags |= B_CLUSTEROK;
+			bdwrite(allocbp);
+		}
+	}
 	*ap->a_bpp = nbp;
 	return (0);
 fail:
@@ -349,8 +376,11 @@
 		ffs_blkfree(ip, *blkp, fs->fs_bsize);
 		deallocated += fs->fs_bsize;
 	}
-	if (allocib != NULL)
+	if (allocib != NULL) {
 		*allocib = 0;
+		if (allocbp != NULL)
+			brelse(allocbp);
+	}
 	if (deallocated) {
 #ifdef QUOTA
 		/*


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




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