Simplify/fix dnode_move() for dn_zfetch
Previous code tried to keep prefetch streams while moving dnode. But it was at least not updating per-stream zs_fetchback pointers, causing use-after-free on next access. Instead of that I see much easier and cleaner to just drop old prefetch state and start new from scratch. Reviewed-by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Igor Kozhukhov <igor@dilos.org> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored-By: iXsystems, Inc. Closes #11936 Closes #11998
This commit is contained in:
parent
85071b2ff5
commit
0db64e9036
|
@ -754,7 +754,6 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
|
|||
ASSERT(!RW_LOCK_HELD(&odn->dn_struct_rwlock));
|
||||
ASSERT(MUTEX_NOT_HELD(&odn->dn_mtx));
|
||||
ASSERT(MUTEX_NOT_HELD(&odn->dn_dbufs_mtx));
|
||||
ASSERT(!MUTEX_HELD(&odn->dn_zfetch.zf_lock));
|
||||
|
||||
/* Copy fields. */
|
||||
ndn->dn_objset = odn->dn_objset;
|
||||
|
@ -822,9 +821,7 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
|
|||
ndn->dn_newgid = odn->dn_newgid;
|
||||
ndn->dn_newprojid = odn->dn_newprojid;
|
||||
ndn->dn_id_flags = odn->dn_id_flags;
|
||||
dmu_zfetch_init(&ndn->dn_zfetch, NULL);
|
||||
list_move_tail(&ndn->dn_zfetch.zf_stream, &odn->dn_zfetch.zf_stream);
|
||||
ndn->dn_zfetch.zf_dnode = odn->dn_zfetch.zf_dnode;
|
||||
dmu_zfetch_init(&ndn->dn_zfetch, ndn);
|
||||
|
||||
/*
|
||||
* Update back pointers. Updating the handle fixes the back pointer of
|
||||
|
@ -832,9 +829,6 @@ dnode_move_impl(dnode_t *odn, dnode_t *ndn)
|
|||
*/
|
||||
ASSERT(ndn->dn_handle->dnh_dnode == odn);
|
||||
ndn->dn_handle->dnh_dnode = ndn;
|
||||
if (ndn->dn_zfetch.zf_dnode == odn) {
|
||||
ndn->dn_zfetch.zf_dnode = ndn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invalidate the original dnode by clearing all of its back pointers.
|
||||
|
|
Loading…
Reference in New Issue