mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-28 17:39:23 +03:00
Illumos #3875
3875 panic in zfs_root() after failed rollback Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Approved by: Gordon Ross <gwr@nexenta.com> References: https://www.illumos.org/issues/3875 illumos/illumos-gate@91948b51b8 Ported-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Issue #1775
This commit is contained in:
committed by
Brian Behlendorf
parent
1958067629
commit
831baf06ef
+52
-49
@@ -1453,7 +1453,9 @@ EXPORT_SYMBOL(zfs_vget);
|
||||
* Block out VFS ops and close zfs_sb_t
|
||||
*
|
||||
* Note, if successful, then we return with the 'z_teardown_lock' and
|
||||
* 'z_teardown_inactive_lock' write held.
|
||||
* 'z_teardown_inactive_lock' write held. We leave ownership of the underlying
|
||||
* dataset and objset intact so that they can be atomically handed off during
|
||||
* a subsequent rollback or recv operation and the resume thereafter.
|
||||
*/
|
||||
int
|
||||
zfs_suspend_fs(zfs_sb_t *zsb)
|
||||
@@ -1463,8 +1465,6 @@ zfs_suspend_fs(zfs_sb_t *zsb)
|
||||
if ((error = zfs_sb_teardown(zsb, B_FALSE)) != 0)
|
||||
return (error);
|
||||
|
||||
dmu_objset_disown(zsb->z_os, zsb);
|
||||
|
||||
return (0);
|
||||
}
|
||||
EXPORT_SYMBOL(zfs_suspend_fs);
|
||||
@@ -1476,66 +1476,69 @@ int
|
||||
zfs_resume_fs(zfs_sb_t *zsb, const char *osname)
|
||||
{
|
||||
int err;
|
||||
znode_t *zp;
|
||||
uint64_t sa_obj = 0;
|
||||
|
||||
ASSERT(RRW_WRITE_HELD(&zsb->z_teardown_lock));
|
||||
ASSERT(RW_WRITE_HELD(&zsb->z_teardown_inactive_lock));
|
||||
|
||||
err = dmu_objset_own(osname, DMU_OST_ZFS, B_FALSE, zsb, &zsb->z_os);
|
||||
if (err) {
|
||||
zsb->z_os = NULL;
|
||||
} else {
|
||||
znode_t *zp;
|
||||
uint64_t sa_obj = 0;
|
||||
/*
|
||||
* We already own this, so just hold and rele it to update the
|
||||
* objset_t, as the one we had before may have been evicted.
|
||||
*/
|
||||
VERIFY0(dmu_objset_hold(osname, zsb, &zsb->z_os));
|
||||
VERIFY3P(zsb->z_os->os_dsl_dataset->ds_owner, ==, zsb);
|
||||
VERIFY(dsl_dataset_long_held(zsb->z_os->os_dsl_dataset));
|
||||
dmu_objset_rele(zsb->z_os, zsb);
|
||||
|
||||
/*
|
||||
* Make sure version hasn't changed
|
||||
*/
|
||||
/*
|
||||
* Make sure version hasn't changed
|
||||
*/
|
||||
|
||||
err = zfs_get_zplprop(zsb->z_os, ZFS_PROP_VERSION,
|
||||
&zsb->z_version);
|
||||
err = zfs_get_zplprop(zsb->z_os, ZFS_PROP_VERSION,
|
||||
&zsb->z_version);
|
||||
|
||||
if (err)
|
||||
goto bail;
|
||||
if (err)
|
||||
goto bail;
|
||||
|
||||
err = zap_lookup(zsb->z_os, MASTER_NODE_OBJ,
|
||||
ZFS_SA_ATTRS, 8, 1, &sa_obj);
|
||||
err = zap_lookup(zsb->z_os, MASTER_NODE_OBJ,
|
||||
ZFS_SA_ATTRS, 8, 1, &sa_obj);
|
||||
|
||||
if (err && zsb->z_version >= ZPL_VERSION_SA)
|
||||
goto bail;
|
||||
if (err && zsb->z_version >= ZPL_VERSION_SA)
|
||||
goto bail;
|
||||
|
||||
if ((err = sa_setup(zsb->z_os, sa_obj,
|
||||
zfs_attr_table, ZPL_END, &zsb->z_attr_table)) != 0)
|
||||
goto bail;
|
||||
if ((err = sa_setup(zsb->z_os, sa_obj,
|
||||
zfs_attr_table, ZPL_END, &zsb->z_attr_table)) != 0)
|
||||
goto bail;
|
||||
|
||||
if (zsb->z_version >= ZPL_VERSION_SA)
|
||||
sa_register_update_callback(zsb->z_os,
|
||||
zfs_sa_upgrade);
|
||||
if (zsb->z_version >= ZPL_VERSION_SA)
|
||||
sa_register_update_callback(zsb->z_os,
|
||||
zfs_sa_upgrade);
|
||||
|
||||
VERIFY(zfs_sb_setup(zsb, B_FALSE) == 0);
|
||||
VERIFY(zfs_sb_setup(zsb, B_FALSE) == 0);
|
||||
|
||||
zfs_set_fuid_feature(zsb);
|
||||
zsb->z_rollback_time = jiffies;
|
||||
zfs_set_fuid_feature(zsb);
|
||||
zsb->z_rollback_time = jiffies;
|
||||
|
||||
/*
|
||||
* Attempt to re-establish all the active inodes with their
|
||||
* dbufs. If a zfs_rezget() fails, then we unhash the inode
|
||||
* and mark it stale. This prevents a collision if a new
|
||||
* inode/object is created which must use the same inode
|
||||
* number. The stale inode will be be released when the
|
||||
* VFS prunes the dentry holding the remaining references
|
||||
* on the stale inode.
|
||||
*/
|
||||
mutex_enter(&zsb->z_znodes_lock);
|
||||
for (zp = list_head(&zsb->z_all_znodes); zp;
|
||||
zp = list_next(&zsb->z_all_znodes, zp)) {
|
||||
err2 = zfs_rezget(zp);
|
||||
if (err2) {
|
||||
remove_inode_hash(ZTOI(zp));
|
||||
zp->z_is_stale = B_TRUE;
|
||||
}
|
||||
/*
|
||||
* Attempt to re-establish all the active inodes with their
|
||||
* dbufs. If a zfs_rezget() fails, then we unhash the inode
|
||||
* and mark it stale. This prevents a collision if a new
|
||||
* inode/object is created which must use the same inode
|
||||
* number. The stale inode will be be released when the
|
||||
* VFS prunes the dentry holding the remaining references
|
||||
* on the stale inode.
|
||||
*/
|
||||
mutex_enter(&zsb->z_znodes_lock);
|
||||
for (zp = list_head(&zsb->z_all_znodes); zp;
|
||||
zp = list_next(&zsb->z_all_znodes, zp)) {
|
||||
err = zfs_rezget(zp);
|
||||
if (err) {
|
||||
remove_inode_hash(ZTOI(zp));
|
||||
zp->z_is_stale = B_TRUE;
|
||||
}
|
||||
mutex_exit(&zsb->z_znodes_lock);
|
||||
}
|
||||
mutex_exit(&zsb->z_znodes_lock);
|
||||
|
||||
bail:
|
||||
/* release the VFS ops */
|
||||
@@ -1544,8 +1547,8 @@ bail:
|
||||
|
||||
if (err) {
|
||||
/*
|
||||
* Since we couldn't reopen zfs_sb_t or, or
|
||||
* setup the sa framework force unmount this file system.
|
||||
* Since we couldn't setup the sa framework, try to force
|
||||
* unmount this file system.
|
||||
*/
|
||||
if (zsb->z_os)
|
||||
(void) zfs_umount(zsb->z_sb);
|
||||
|
||||
Reference in New Issue
Block a user