svn commit: r215117 - head/sys/ufs/ffs

Konstantin Belousov kib at FreeBSD.org
Thu Nov 11 11:54:01 UTC 2010


Author: kib
Date: Thu Nov 11 11:54:01 2010
New Revision: 215117
URL: http://svn.freebsd.org/changeset/base/215117

Log:
  The softdep_setup_freeblocks() adds worklist items before
  deallocate_dependencies() is done. This opens a race between softdep
  thread and the thread that does the truncation:
    A write of the indirect block causes the freeblks to become
    ALLCOMPLETE while softdep_setup_freeblocks() dropped softdep lock. And
    then, softdep_disk_write_complete() would reassign the workitem to the
    mount point worklist, causing premature processing of the workitem, or
    journal write exhaust the fb_jfreeblkhd and handle_written_jfreeblk does
    the same reassign.
  indir_trunc() then would find the indirect block that is locked (with lock
  owned by kernel) but without any dependencies, causing it to hang in
  getblk() waiting for buffer lock.
  
  Do not mark freeblks as DEPCOMPLETE until deallocate_dependencies()
  finished.
  
  Analyzed, suggested and reviewed by:	jeff
  Tested by:	pho

Modified:
  head/sys/ufs/ffs/ffs_softdep.c

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c	Thu Nov 11 11:46:19 2010	(r215116)
+++ head/sys/ufs/ffs/ffs_softdep.c	Thu Nov 11 11:54:01 2010	(r215117)
@@ -5270,7 +5270,7 @@ softdep_setup_freeblocks(ip, length, fla
 	if (delay)
 		WORKLIST_INSERT(&bp->b_dep, &freeblks->fb_list);
 	else if (needj)
-		freeblks->fb_state |= DEPCOMPLETE | COMPLETE;
+		freeblks->fb_state |= COMPLETE;
 	/*
 	 * Because the file length has been truncated to zero, any
 	 * pending block allocation dependency structures associated
@@ -5332,8 +5332,9 @@ restart:
 	if (inodedep_lookup(mp, ip->i_number, 0, &inodedep) != 0)
 		(void) free_inodedep(inodedep);
 
-	if (delay) {
+	if (delay || needj)
 		freeblks->fb_state |= DEPCOMPLETE;
+	if (delay) {
 		/*
 		 * If the inode with zeroed block pointers is now on disk
 		 * we can start freeing blocks. Add freeblks to the worklist
@@ -5344,6 +5345,8 @@ restart:
 		if ((freeblks->fb_state & ALLCOMPLETE) == ALLCOMPLETE)
 			add_to_worklist(&freeblks->fb_list, 1);
 	}
+	if (needj && LIST_EMPTY(&freeblks->fb_jfreeblkhd))
+		needj = 0;
 
 	FREE_LOCK(&lk);
 	/*


More information about the svn-src-head mailing list