diff options
author | Brian Behlendorf <[email protected]> | 2013-03-19 12:05:08 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2013-03-19 13:01:01 -0700 |
commit | 5dc6af0eec29b119b731c793037fd77214fc9438 (patch) | |
tree | f5a0b9d94d2593a037d92e603d6264b42df03adb /module/zfs | |
parent | 30b92c1de68ced4bee235f879791ee316314a197 (diff) |
Add zio_ddt_free()+ddt_phys_decref() error handling
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 <[email protected]>
Closes #1308
Diffstat (limited to 'module/zfs')
-rw-r--r-- | module/zfs/ddt.c | 6 | ||||
-rw-r--r-- | module/zfs/zio.c | 7 |
2 files changed, 9 insertions, 4 deletions
diff --git a/module/zfs/ddt.c b/module/zfs/ddt.c index ef868619a..2d8763a54 100644 --- a/module/zfs/ddt.c +++ b/module/zfs/ddt.c @@ -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 diff --git a/module/zfs/zio.c b/module/zfs/zio.c index 77b1764d7..0622553f5 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -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); |