Handle the case of a vnode flush while dirops are active correctly in

lfs_segwrite.  Also, make sure a flush is called in SET_DIROP before sleeping
on its results.  Addresses PR #8863.
This commit is contained in:
perseant 1999-12-03 21:47:44 +00:00
parent 184f8b2c39
commit 22979769c0
2 changed files with 30 additions and 25 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_segment.c,v 1.36 1999/11/17 20:08:30 perseant Exp $ */
/* $NetBSD: lfs_segment.c,v 1.37 1999/12/03 21:47:44 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -484,32 +484,30 @@ lfs_segwrite(mp, flags)
/*
* If lfs_flushvp is non-NULL, we are called from lfs_vflush,
* in which case we have to flush *all* buffers off of this vnode.
* We don't care about other nodes, but write any non-dirop nodes
* anyway in anticipation of another getnewvnode().
*
* If we're cleaning we only write cleaning and ifile blocks, and
* no dirops, since otherwise we'd risk corruption in a crash.
*/
if((sp->seg_flags & SEGM_CLEAN) && !(fs->lfs_flushvp))
if(fs->lfs_flushvp)
lfs_writevnodes(fs, mp, sp, VN_REG);
else if(sp->seg_flags & SEGM_CLEAN)
lfs_writevnodes(fs, mp, sp, VN_CLEAN);
else {
lfs_writevnodes(fs, mp, sp, VN_REG);
/*
* XXX KS - If we're cleaning, we can't wait for dirops,
* because they might be waiting on us. The downside of this
* is that, if we write anything besides cleaning blocks
* while cleaning, the checkpoint is not completely
* consistent.
*/
if(!(sp->seg_flags & SEGM_CLEAN)) {
while(fs->lfs_dirops)
if((error = tsleep(&fs->lfs_writer, PRIBIO + 1,
"lfs writer", 0)))
{
free(sp->bpp, M_SEGMENT);
free(sp, M_SEGMENT);
return (error);
}
fs->lfs_writer++;
writer_set=1;
lfs_writevnodes(fs, mp, sp, VN_DIROP);
((SEGSUM *)(sp->segsum))->ss_flags &= ~(SS_CONT);
}
while(fs->lfs_dirops)
if((error = tsleep(&fs->lfs_writer, PRIBIO + 1,
"lfs writer", 0)))
{
free(sp->bpp, M_SEGMENT);
free(sp, M_SEGMENT);
return (error);
}
fs->lfs_writer++;
writer_set=1;
lfs_writevnodes(fs, mp, sp, VN_DIROP);
((SEGSUM *)(sp->segsum))->ss_flags &= ~(SS_CONT);
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: lfs_vnops.c,v 1.32 1999/11/15 18:49:14 fvdl Exp $ */
/* $NetBSD: lfs_vnops.c,v 1.33 1999/12/03 21:47:44 perseant Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -304,9 +304,16 @@ static int lfs_set_dirop(fs)
while (fs->lfs_writer || lfs_dirvcount>LFS_MAXDIROP) {
if(fs->lfs_writer)
tsleep(&fs->lfs_dirops, PRIBIO + 1, "lfs_dirop", 0);
if(lfs_dirvcount > LFS_MAXDIROP && fs->lfs_dirops==0) {
++fs->lfs_writer;
lfs_flush(fs, 0);
if(--fs->lfs_writer==0)
wakeup(&fs->lfs_dirops);
}
if(lfs_dirvcount > LFS_MAXDIROP) {
#ifdef DEBUG_LFS
printf("(dirvcount=%d)\n",lfs_dirvcount);
printf("lfs_set_dirop: sleeping with dirops=%d, dirvcount=%d\n",fs->lfs_dirops,lfs_dirvcount);
#endif
if((error=tsleep(&lfs_dirvcount, PCATCH|PUSER, "lfs_maxdirop", 0))!=0)
return error;