Patch from Kirk McKusick to fix an ordering problem in softdep_setup_freeblks()

that could cause an inode to be reused prematurely (possibly resulting in the
file containing garbage blocks).
This commit is contained in:
mycroft 2000-12-13 20:07:32 +00:00
parent c2cfcae955
commit 61a6479ab1
1 changed files with 20 additions and 17 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ffs_softdep.c,v 1.11 2000/12/13 15:32:31 chs Exp $ */ /* $NetBSD: ffs_softdep.c,v 1.12 2000/12/13 20:07:32 mycroft Exp $ */
/* /*
* Copyright 1998 Marshall Kirk McKusick. All Rights Reserved. * Copyright 1998 Marshall Kirk McKusick. All Rights Reserved.
@ -1620,7 +1620,7 @@ softdep_setup_freeblocks(ip, length)
struct buf *bp; struct buf *bp;
struct bufq_head fbqh; struct bufq_head fbqh;
struct fs *fs = ip->i_fs; struct fs *fs = ip->i_fs;
int i, error; int i, error, delay;
#ifdef FFS_EI #ifdef FFS_EI
const int needswap = UFS_FSNEEDSWAP(fs); const int needswap = UFS_FSNEEDSWAP(fs);
#endif #endif
@ -1672,6 +1672,16 @@ softdep_setup_freeblocks(ip, length)
(void) inodedep_lookup(fs, ip->i_number, DEPALLOC, &inodedep); (void) inodedep_lookup(fs, ip->i_number, DEPALLOC, &inodedep);
if ((inodedep->id_state & IOSTARTED) != 0) if ((inodedep->id_state & IOSTARTED) != 0)
panic("softdep_setup_freeblocks: inode busy"); panic("softdep_setup_freeblocks: inode busy");
/*
* Add the freeblks structure to the list of operations that
* must await the zero'ed inode being written to disk. If we
* still have a bitmap dependency (delay == 0), then the inode
* has never been written to disk, so we can process the
* freeblks below once we have deleted the dependencies.
*/
delay = (inodedep->id_state & DEPCOMPLETE);
if (delay)
WORKLIST_INSERT(&inodedep->id_bufwait, &freeblks->fb_list);
/* /*
* Because the file length has been truncated to zero, any * Because the file length has been truncated to zero, any
* pending block allocation dependency structures associated * pending block allocation dependency structures associated
@ -1708,23 +1718,16 @@ softdep_setup_freeblocks(ip, length)
ACQUIRE_LOCK(&lk); ACQUIRE_LOCK(&lk);
} }
softdep_free_pagecache(&fbqh); softdep_free_pagecache(&fbqh);
if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) != 0)
(void) free_inodedep(inodedep);
FREE_LOCK(&lk);
/* /*
* Add the freeblks structure to the list of operations that * If the inode has never been written to disk (delay == 0),
* must await the zero'ed inode being written to disk. If we * then we can process the freeblks now that we have deleted
* still have a bitmap dependency, then the inode has never been * the dependencies.
* written to disk, so we can process the freeblks immediately.
* If the inodedep does not exist, then the zero'ed inode has
* been written and we can also proceed.
*/ */
if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) == 0 || if (!delay)
free_inodedep(inodedep) ||
(inodedep->id_state & DEPCOMPLETE) == 0) {
FREE_LOCK(&lk);
handle_workitem_freeblocks(freeblks); handle_workitem_freeblocks(freeblks);
} else {
WORKLIST_INSERT(&inodedep->id_bufwait, &freeblks->fb_list);
FREE_LOCK(&lk);
}
} }
/* /*
@ -2042,7 +2045,7 @@ handle_workitem_freeblocks(freeblks)
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (freeblks->fb_chkcnt != blocksreleased) if (freeblks->fb_chkcnt != blocksreleased)
panic("handle_workitem_freeblocks: block count"); printf("handle_workitem_freeblocks: block count");
if (allerror) if (allerror)
softdep_error("handle_workitem_freeblks", allerror); softdep_error("handle_workitem_freeblks", allerror);
#endif /* DIAGNOSTIC */ #endif /* DIAGNOSTIC */