Fix insufficient locking in dedup verify

Introduction of dde_io_lock removed global DDT lock acquisition
from write completion.  As result, white ZIO ABD could be freed
while zio_ddt_collision() is comparing against it.  Taking there
dde_io_lock should fix the issue.

Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Alexander Motin <[email protected]>
Closes #17960
Closes #18712
Closes #18720
This commit is contained in:
Alexander Motin authored and GitHub committed 2026-07-01 13:50:17 -07:00
1 parent 604805c02e
commit f607ef7e72
1 file changed
+18 -8
+18 -8
View File
@@ -3587,16 +3587,26 @@ zio_ddt_collision(zio_t *zio, ddt_t *ddt, ddt_entry_t *dde)
if (dde->dde_io == NULL)
continue;
/*
* Lock dde_io to prevent the lead zio from completing
* and freeing its ABD while we compare against it.
*/
mutex_enter(&dde->dde_io->dde_io_lock);
zio_t *lio = dde->dde_io->dde_lead_zio[p];
if (lio == NULL)
if (lio == NULL) {
mutex_exit(&dde->dde_io->dde_io_lock);
continue;
if (do_raw)
return (lio->io_size != zio->io_size ||
abd_cmp(zio->io_abd, lio->io_abd) != 0);
return (lio->io_orig_size != zio->io_orig_size ||
abd_cmp(zio->io_orig_abd, lio->io_orig_abd) != 0);
}
boolean_t collision;
if (do_raw) {
collision = lio->io_size != zio->io_size ||
abd_cmp(zio->io_abd, lio->io_abd) != 0;
} else {
collision = lio->io_orig_size != zio->io_orig_size ||
abd_cmp(zio->io_orig_abd, lio->io_orig_abd) != 0;
}
mutex_exit(&dde->dde_io->dde_io_lock);
return (collision);
}
for (int p = 0; p < DDT_NPHYS(ddt); p++) {