svn commit: r208799 - stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs

Martin Matuska mm at FreeBSD.org
Fri Jun 4 08:46:27 UTC 2010


Author: mm
Date: Fri Jun  4 08:46:26 2010
New Revision: 208799
URL: http://svn.freebsd.org/changeset/base/208799

Log:
  MFC r208689:
  
  Fix ZIL close when doing zfs rollback or zfs receive on a mounted dataset.
  
  The fix is a partial import and merge of OpenSolaris onnv revisions
  8227:f7d7be9b1f56. and 9292:e112194b5b73
  
  Reviewed by:	pjd, delphij (mentor)
  Obtained from:	OpenSolaris (Bug ID 6798298)
  Approved by:	re (kib)

Modified:
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/geom/sched/   (props changed)

Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
==============================================================================
--- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Fri Jun  4 08:19:43 2010	(r208798)
+++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Fri Jun  4 08:46:26 2010	(r208799)
@@ -499,6 +499,12 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t
 	dmu_objset_set_user(zfsvfs->z_os, zfsvfs);
 	mutex_exit(&zfsvfs->z_os->os->os_user_ptr_lock);
 
+	zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data);
+	if (zil_disable) {
+		zil_destroy(zfsvfs->z_log, B_FALSE);
+		zfsvfs->z_log = NULL;
+	}
+
 	/*
 	 * If we are not mounting (ie: online recv), then we don't
 	 * have to worry about replaying the log as we blocked all
@@ -512,21 +518,45 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t
 		 * allow replays to succeed.
 		 */
 		readonly = zfsvfs->z_vfs->vfs_flag & VFS_RDONLY;
-		zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY;
-
-		/*
-		 * Parse and replay the intent log.
-		 */
-		zil_replay(zfsvfs->z_os, zfsvfs, &zfsvfs->z_assign,
-		    zfs_replay_vector, zfs_unlinked_drain);
+		if (readonly != 0)
+			zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY;
+		else
+			zfs_unlinked_drain(zfsvfs);
 
-		zfs_unlinked_drain(zfsvfs);
+		if (zfsvfs->z_log) {
+			/*
+			 * Parse and replay the intent log.
+			 *
+			 * Because of ziltest, this must be done after
+			 * zfs_unlinked_drain().  (Further note: ziltest
+			 * doesn't use readonly mounts, where
+			 * zfs_unlinked_drain() isn't called.)  This is because
+			 * ziltest causes spa_sync() to think it's committed,
+			 * but actually it is not, so the intent log contains
+			 * many txg's worth of changes.
+			 *
+			 * In particular, if object N is in the unlinked set in
+			 * the last txg to actually sync, then it could be
+			 * actually freed in a later txg and then reallocated
+			 * in a yet later txg.  This would write a "create
+			 * object N" record to the intent log.  Normally, this
+			 * would be fine because the spa_sync() would have
+			 * written out the fact that object N is free, before
+			 * we could write the "create object N" intent log
+			 * record.
+			 *
+			 * But when we are in ziltest mode, we advance the "open
+			 * txg" without actually spa_sync()-ing the changes to
+			 * disk.  So we would see that object N is still
+			 * allocated and in the unlinked set, and there is an
+			 * intent log record saying to allocate it.
+			 */
+			zil_replay(zfsvfs->z_os, zfsvfs, &zfsvfs->z_assign,
+			    zfs_replay_vector, zfs_unlinked_drain);
+		}
 		zfsvfs->z_vfs->vfs_flag |= readonly; /* restore readonly bit */
 	}
 
-	if (!zil_disable)
-		zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data);
-
 	return (0);
 }
 


More information about the svn-src-stable-8 mailing list