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:
parent
184f8b2c39
commit
22979769c0
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue