diff options
author | Alexander Motin <mav@FreeBSD.org> | 2021-05-07 22:07:03 +0000 |
---|---|---|
committer | Brian Behlendorf <behlendorf1@llnl.gov> | 2021-05-10 19:13:29 +0000 |
commit | 0db64e9036436f92bbd1ab1592b704a5b9b1412f (patch) | |
tree | 9e70cbc6a45e2d78d89a3d58c524469c087689da | |
parent | 85071b2ff5ad71d998963894c5cf4d701f3700a4 (diff) | |
download | src-0db64e9036436f92bbd1ab1592b704a5b9b1412f.tar.gz src-0db64e9036436f92bbd1ab1592b704a5b9b1412f.zip |
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
-rw-r--r-- | module/zfs/dnode.c | 8 |
1 files changed, 1 insertions, 7 deletions
diff --git a/module/zfs/dnode.c b/module/zfs/dnode.c index eaba9c0c0e7f..0fc788e28fe4 100644 --- a/module/zfs/dnode.c +++ b/module/zfs/dnode.c @@ -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. |