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
This commit is contained in:
Martin Matuska 2010-06-01 08:43:46 +00:00
parent 6e6a072d39
commit dc5d34e454

View File

@ -499,6 +499,12 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
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 mounting)
* allow replays to succeed.
*/
readonly = zfsvfs->z_vfs->vfs_flag & VFS_RDONLY;
zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY;
if (readonly != 0)
zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY;
else
zfs_unlinked_drain(zfsvfs);
/*
* Parse and replay the intent log.
*/
zil_replay(zfsvfs->z_os, zfsvfs, &zfsvfs->z_assign,
zfs_replay_vector, zfs_unlinked_drain);
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);
}