Author: mm
Date: Tue Jun  1 08:43:46 2010
New Revision: 208689
URL: http://svn.freebsd.org/changeset/base/208689

Log:
  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
  
  Approved by:  pjd, delphij (mentor)
  Obtained from:        OpenSolaris (Bug ID 6798298)
  MFC after:    3 days

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c    Tue Jun 
 1 05:32:59 2010        (r208688)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c    Tue Jun 
 1 08:43:46 2010        (r208689)
@@ -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);
 }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to