summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2013-03-19 12:05:08 -0700
committerBrian Behlendorf <[email protected]>2013-03-19 13:01:01 -0700
commit5dc6af0eec29b119b731c793037fd77214fc9438 (patch)
treef5a0b9d94d2593a037d92e603d6264b42df03adb /module/zfs
parent30b92c1de68ced4bee235f879791ee316314a197 (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.c6
-rw-r--r--module/zfs/zio.c7
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);