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:
parent
6e6a072d39
commit
dc5d34e454
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user