Project

General

Profile

Bug #2649

dedup=verify can leave the dedup bit set on a non-dedup block

Added by George Wilson about 8 years ago. Updated about 8 years ago.

Status:
New
Priority:
Normal
Assignee:
Category:
zfs - Zettabyte File System
Start date:
2012-04-22
Due date:
% Done:

0%

Estimated time:
Difficulty:
Medium
Tags:
needs-triage
Gerrit CR:

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.

History

#1

Updated by Jim Klimov about 8 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).

Also available in: Atom PDF