Actions
Bug #2649
opendedup=verify can leave the dedup bit set on a non-dedup block
Start date:
2012-04-22
Due date:
% Done:
0%
Estimated time:
Difficulty:
Medium
Tags:
needs-triage
Gerrit CR:
External Bug:
Description
If a dataset has 'dedup=verify' enabled it is possible for zio_ddt_write() to write out a dedup-ed block that is never entered into the DDT.
As seen in bug #2024 (https://www.illumos.org/issues/2024) it's possible to hit this condition.
The problem is in this code path in zio_ddt_write():
if (zp->zp_dedup_verify && zio_ddt_collision(zio, ddt, dde)) {
/*
* If we're using a weak checksum, upgrade to a strong checksum
* and try again. If we're already using a strong checksum,
* we can't resolve it, so just convert to an ordinary write.
* (And automatically e-mail a paper to Nature?)
*/
if (!zio_checksum_table[zp->zp_checksum].ci_dedup) {
zp->zp_checksum = spa_dedup_checksum(spa);
zio_pop_transforms(zio);
zio->io_stage = ZIO_STAGE_OPEN;
BP_ZERO(bp);
} else {
zp->zp_dedup = 0;
}
zio->io_pipeline = ZIO_WRITE_PIPELINE;
ddt_exit(ddt);
return (ZIO_PIPELINE_CONTINUE);
}
The issue is that in the else clause we set zp->zp_dedup = 0 but we never reset the value of the blkptr. The end result is a bp written to disk that still has the dedup bit set. Any attempts to free that block will result in a panic.
Updated by Jim Klimov about 11 years ago
Webrev http://code.delphix.com/webrev-2649/ LGTMed on the list a few times, I'm not sure it was integrated yet (more features were requested by reviewers, like a kstat and a syslog message on hitting this condition).
Actions