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

Jeff Roberson jeff at FreeBSD.org
Tue Jan 14 02:00:24 UTC 2020


Author: jeff
Date: Tue Jan 14 02:00:24 2020
New Revision: 356714
URL: https://svnweb.freebsd.org/changeset/base/356714

Log:
  Fix a long standing bug in journaled soft-updates.  The dirrem structure
  needs to handle file removal, directory removal, file move, directory move,
  etc.  The code in handle_workitem_remove() needs to propagate any completed
  journal entries to the write that will render the change stable.  In the
  case of a moved directory this means the new parent.  However, for an
  overwrite that frees a directory (DIRCHG) we must move the jsegdep to the
  removed inode to be released when it is stable in the cg bitmap or the
  unlinked inode list.  This case was previously unhandled and caused a
  panic.
  
  Reported by:	mckusick, pho
  Reviewed by:	mckusick
  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	Tue Jan 14 01:43:04 2020	(r356713)
+++ head/sys/ufs/ffs/ffs_softdep.c	Tue Jan 14 02:00:24 2020	(r356714)
@@ -9849,14 +9849,20 @@ handle_workitem_remove(dirrem, flags)
 	/*
 	 * Move all dependencies waiting on the remove to complete
 	 * from the dirrem to the inode inowait list to be completed
-	 * after the inode has been updated and written to disk.  Any
-	 * marked MKDIR_PARENT are saved to be completed when the .. ref
-	 * is removed.
+	 * after the inode has been updated and written to disk.
+	 *
+	 * Any marked MKDIR_PARENT are saved to be completed when the 
+	 * dotdot ref is removed unless DIRCHG is specified.  For
+	 * directory change operations there will be no further
+	 * directory writes and the jsegdeps need to be moved along
+	 * with the rest to be completed when the inode is free or
+	 * stable in the inode free list.
 	 */
 	LIST_INIT(&dotdotwk);
 	while ((wk = LIST_FIRST(&dirrem->dm_jwork)) != NULL) {
 		WORKLIST_REMOVE(wk);
-		if (wk->wk_state & MKDIR_PARENT) {
+		if ((dirrem->dm_state & DIRCHG) == 0 &&
+		    wk->wk_state & MKDIR_PARENT) {
 			wk->wk_state &= ~MKDIR_PARENT;
 			WORKLIST_INSERT(&dotdotwk, wk);
 			continue;


More information about the svn-src-head mailing list