Skip to content

Commit

Permalink
Add zio_ddt_free()+ddt_phys_decref() error handling
Browse files Browse the repository at this point in the history
The assumption in zio_ddt_free() is that ddt_phys_select() must
always find a match.  However, if that fails due to a damaged
DDT or some other reason the code will NULL dereference in
ddt_phys_decref().

While this should never happen it has been observed on various
platforms.  The result is that unless your willing to patch the
ZFS code the pool is inaccessible.  Therefore, we're choosing
to more gracefully handle this case rather than leave it fatal.

http://mail.opensolaris.org/pipermail/zfs-discuss/2012-February/050972.html

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #1308
  • Loading branch information
behlendorf committed Mar 19, 2013
1 parent 30b92c1 commit 5dc6af0
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 4 deletions.
6 changes: 4 additions & 2 deletions module/zfs/ddt.c
Expand Up @@ -323,8 +323,10 @@ ddt_phys_addref(ddt_phys_t *ddp)
void
ddt_phys_decref(ddt_phys_t *ddp)
{
ASSERT((int64_t)ddp->ddp_refcnt > 0);
ddp->ddp_refcnt--;
if (ddp) {
ASSERT((int64_t)ddp->ddp_refcnt > 0);
ddp->ddp_refcnt--;
}
}

void
Expand Down
7 changes: 5 additions & 2 deletions module/zfs/zio.c
Expand Up @@ -2249,8 +2249,11 @@ zio_ddt_free(zio_t *zio)

ddt_enter(ddt);
freedde = dde = ddt_lookup(ddt, bp, B_TRUE);
ddp = ddt_phys_select(dde, bp);
ddt_phys_decref(ddp);
if (dde) {
ddp = ddt_phys_select(dde, bp);
if (ddp)
ddt_phys_decref(ddp);
}
ddt_exit(ddt);

return (ZIO_PIPELINE_CONTINUE);
Expand Down

0 comments on commit 5dc6af0

Please sign in to comment.