Date: Wed, 23 Feb 2000 22:55:06 -0800 From: Alfred Perlstein <bright@wintelcom.net> To: Matthew Dillon <dillon@apollo.backplane.com> Cc: Ian Dowse <iedowse@maths.tcd.ie>, mckusick@freebsd.org, current@freebsd.org Subject: Re: ffs_blkfree: freeing free block (was Re: Panic (pmap)) Message-ID: <20000223225505.A21720@fw.wintelcom.net> In-Reply-To: <200002240556.VAA34592@apollo.backplane.com>; from dillon@apollo.backplane.com on Wed, Feb 23, 2000 at 09:56:35PM -0800 References: <200002232235.aa22335@salmon.maths.tcd.ie> <200002240227.SAA33299@apollo.backplane.com> <200002240556.VAA34592@apollo.backplane.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Er, shouldn't you guys let Kirk know, not only is he "MAINTAINER", but pretty much mostly "CREATOR" :) Kirk, another issue with running out of space in FFS seems to have come up: * Matthew Dillon <dillon@apollo.backplane.com> [000223 18:57] wrote: > :Ian Dowse <iedowse@maths.tcd.ie> wrote: > :I think I've found it. Here's an easy way to repeat the problem to > :start with: > : > : mount_mfs -T fd1440 none /mnt > : cd /mnt > : dd if=/dev/zero bs=4k of=test seek=1036 count=1 > : dd if=/dev/zero bs=4k of=test1 count=1 > : dd if=/dev/zero bs=4k of=test2 > : rm test1 > : dd if=/dev/zero bs=4k of=test seek=8000 count=1 > : echo > test > : > :It looks as if the problem is in ffs_balloc(), and occurs as follows: > : - ffs_balloc() is asked to allocate a doubly indirect block. > : - The first-level indirection block already exists > : - The second-level indirection block does not exist, but is > : successfully allocated. > : - This block is linked into the first-level indirection block by > : the line: > : > : bap[indirs[i - 1].in_off] = nb; > : > : - Allocation of the data block fails. > : - All allocated blocks are then released, but there is still > : a link in the first-level indirection block to what is > : now a free block. > : > :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. > : > :Ian > > Great detective work! The 'allocib' variable is used to unwind the > 'first' new indirect block allocation, but it is *only* initialized > for the Level 0 block. So the unwinding only works when the Level 0 > indirect block had to be allocated. When the Level 0 indirect block > is valid and a deeper level indirect block had to be allocated, > allocib is not initialized and the association is not unwound even > though the deeper indirect block is freed when the data block allocation > fails. > > Unfortunately, we can't simply initialize 'allocib' here, because it > would point into the middle of a buffer. The fix is thus not entirely > trivial. > > This is what I think we need to do, but THIS PATCH IS NOT TESTED AND > COULD BE COMPLETELY WRONG. Any filesystem gurus out there who can look > at this and tell me if it's correct? [patch snipped, Matt just re-issued a fixed version] * Matthew Dillon <dillon@apollo.backplane.com> [000223 22:26] wrote: > > Oops, here's a new version of my patch. This one survives Ian's test > script. I was improperly blowing away an 'error' field. > > -Matt > > Index: ffs_balloc.c > =================================================================== > RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_balloc.c,v > retrieving revision 1.25 > diff -u -r1.25 ffs_balloc.c > --- ffs_balloc.c 2000/01/11 08:27:00 1.25 > +++ ffs_balloc.c 2000/02/24 05:44:59 > @@ -77,6 +77,7 @@ > ufs_daddr_t newb, *bap, pref; > int deallocated, osize, nsize, num, i, error; > ufs_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1]; > + int unwindidx = -1; > struct proc *p = curproc; /* XXX */ > > vp = ap->a_vp; > @@ -272,6 +273,8 @@ > } > } > bap[indirs[i - 1].in_off] = nb; > + if (allocib == NULL && unwindidx < 0) > + unwindidx = i - 1; > /* > * If required, write synchronously, otherwise use > * delayed write. > @@ -349,8 +352,28 @@ > ffs_blkfree(ip, *blkp, fs->fs_bsize); > deallocated += fs->fs_bsize; > } > - if (allocib != NULL) > + if (allocib != NULL) { > *allocib = 0; > + } else if (unwindidx >= 0) { > + int r; > + > + r = bread(vp, indirs[unwindidx].in_lbn, > + (int)fs->fs_bsize, NOCRED, &bp); > + if (r) { > + panic("Could not unwind indirect block, error %d", error); > + brelse(bp); > + } else { > + bap = (ufs_daddr_t *)bp->b_data; > + bap[indirs[unwindidx].in_off] = 0; > + if (flags & B_SYNC) { > + bwrite(bp); > + } else { > + if (bp->b_bufsize == fs->fs_bsize) > + bp->b_flags |= B_CLUSTEROK; > + bdwrite(bp); > + } > + } > + } > 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?20000223225505.A21720>