When unwinding a failed allocation, make sure to nuke the unwound block from

the vnode's block list.  This fixes `itrunc3' panics (at least in some cases;
further testing is needed) and prevents further lossage later on.
This commit is contained in:
mycroft 2000-05-28 08:15:40 +00:00
parent bd22f3362b
commit 4fc7b946c2
2 changed files with 33 additions and 26 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_balloc.c,v 1.17 2000/02/25 19:58:25 fvdl Exp $ */
/* $NetBSD: ffs_balloc.c,v 1.18 2000/05/28 08:15:40 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -217,8 +217,8 @@ ffs_balloc(v)
allocblk = allociblk;
if (nb == 0) {
pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
cred, &newb);
error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
&newb);
if (error)
return (error);
nb = newb;
@ -238,6 +238,7 @@ ffs_balloc(v)
if ((error = bwrite(bp)) != 0)
goto fail;
}
unwindidx = 0;
allocib = &ip->i_ffs_ib[indirs[0].in_off];
*allocib = ufs_rw32(nb, needswap);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
@ -256,7 +257,7 @@ ffs_balloc(v)
nb = ufs_rw32(bap[indirs[i].in_off], needswap);
if (i == num)
break;
i += 1;
i++;
if (nb != 0) {
brelse(bp);
continue;
@ -264,7 +265,7 @@ ffs_balloc(v)
if (pref == 0)
pref = ffs_blkpref(ip, lbn, 0, (ufs_daddr_t *)0);
error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
&newb);
&newb);
if (error) {
brelse(bp);
goto fail;
@ -288,6 +289,8 @@ ffs_balloc(v)
goto fail;
}
}
if (unwindidx < 0)
unwindidx = i - 1;
bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap);
/*
* If required, write synchronously, otherwise use
@ -305,7 +308,7 @@ ffs_balloc(v)
if (nb == 0) {
pref = ffs_blkpref(ip, lbn, indirs[i].in_off, &bap[0]);
error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred,
&newb);
&newb);
if (error) {
brelse(bp);
goto fail;
@ -320,8 +323,6 @@ ffs_balloc(v)
softdep_setup_allocindir_page(ip, lbn, bp,
indirs[i].in_off, nb, 0, nbp);
bap[indirs[i].in_off] = ufs_rw32(nb, needswap);
if (allocib == NULL && unwindidx < 0)
unwindidx = i - 1;
/*
* If required, write synchronously, otherwise use
* delayed write.
@ -364,24 +365,30 @@ fail:
ffs_blkfree(ip, *blkp, fs->fs_bsize);
deallocated += fs->fs_bsize;
}
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", r);
brelse(bp);
if (unwindidx >= 0) {
if (unwindidx == 0) {
*allocib = 0;
} else {
bap = (ufs_daddr_t *)bp->b_data;
bap[indirs[unwindidx].in_off] = 0;
if (flags & B_SYNC)
bwrite(bp);
else
bdwrite(bp);
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", r);
brelse(bp);
} else {
bap = (ufs_daddr_t *)bp->b_data;
bap[indirs[unwindidx].in_off] = 0;
if (flags & B_SYNC)
bwrite(bp);
else
bdwrite(bp);
}
}
bp = getblk(vp, indirs[unwindidx + 1].in_lbn,
(int)fs->fs_bsize, 0, 0);
bp->b_flags |= B_INVAL;
brelse(bp);
}
if (deallocated) {
#ifdef QUOTA

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_inode.c,v 1.32 2000/05/28 04:13:58 mycroft Exp $ */
/* $NetBSD: ffs_inode.c,v 1.33 2000/05/28 08:15:42 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -507,7 +507,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
}
bap = (ufs_daddr_t *)bp->b_data;
if (lastbn != -1) {
if (lastbn >= 0) {
MALLOC(copy, ufs_daddr_t *, fs->fs_bsize, M_TEMP, M_WAITOK);
memcpy((caddr_t)copy, (caddr_t)bap, (u_int)fs->fs_bsize);
memset((caddr_t)&bap[last + 1], 0,