mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 19:34:43 +01:00
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:
1 parent
604805c02e
commit
f607ef7e72
1 file changed
+18
-8
+18
-8
@@ -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++) {
|
||||
|
||||
Reference in new issue
Block a user