aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2021-05-07 22:07:03 +0000
committerBrian Behlendorf <behlendorf1@llnl.gov>2021-05-10 19:13:29 +0000
commit0db64e9036436f92bbd1ab1592b704a5b9b1412f (patch)
tree9e70cbc6a45e2d78d89a3d58c524469c087689da
parent85071b2ff5ad71d998963894c5cf4d701f3700a4 (diff)
downloadsrc-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.c8
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.