Delay freeing disk space for file system blocks until all dirty buffers

are safely released. This fixes softdep problems on truncation (deletion)
of files with dirty buffers.

Reviewed by:	jeff@, mckusick@, ps@, tegge@
Tested by: 	glebius@, ps@
MFC after:	3 weeks
This commit is contained in:
Stephan Uphoff 2005-07-31 20:24:14 +00:00
parent 4442c32be7
commit ed8938e082
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=148608
2 changed files with 20 additions and 0 deletions

View file

@ -2045,6 +2045,7 @@ softdep_setup_freeblocks(ip, length, flags)
MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),
M_FREEBLKS, M_SOFTDEP_FLAGS|M_ZERO);
freeblks->fb_list.wk_type = D_FREEBLKS;
freeblks->fb_state = ATTACHED;
freeblks->fb_uid = ip->i_uid;
freeblks->fb_previousinum = ip->i_number;
freeblks->fb_devvp = ip->i_devvp;
@ -2180,6 +2181,20 @@ softdep_setup_freeblocks(ip, length, flags)
ACQUIRE_LOCK(&lk);
if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) != 0)
(void) free_inodedep(inodedep);
if(delay) {
freeblks->fb_state |= DEPCOMPLETE;
/*
* If the inode with zeroed block pointers is now on disk
* we can start freeing blocks. Add freeblks to the worklist
* instead of calling handle_workitem_freeblocks directly as
* it is more likely that additional IO is needed to complete
* the request here than in the !delay case.
*/
if ((freeblks->fb_state & ALLCOMPLETE) == ALLCOMPLETE)
add_to_worklist(&freeblks->fb_list);
}
FREE_LOCK(&lk);
/*
* If the inode has never been written to disk (delay == 0),
@ -4425,6 +4440,10 @@ handle_written_inodeblock(inodedep, bp)
continue;
case D_FREEBLKS:
wk->wk_state |= COMPLETE;
if ((wk->wk_state & ALLCOMPLETE) != ALLCOMPLETE)
continue;
/* -- fall through -- */
case D_FREEFRAG:
case D_DIRREM:
add_to_worklist(wk);

View file

@ -429,6 +429,7 @@ struct freefrag {
*/
struct freeblks {
struct worklist fb_list; /* id_inowait or delayed worklist */
# define fb_state fb_list.wk_state /* inode and dirty block state */
ino_t fb_previousinum; /* inode of previous owner of blocks */
uid_t fb_uid; /* uid of previous owner of blocks */
struct vnode *fb_devvp; /* filesystem device vnode */