Skip to content

Commit 48f376b

Browse files
amotinbehlendorf
authored andcommitted
Improve arc_read() error reporting
Debugging reported NULL de-reference panic in dnode_hold_impl() I found that for certain types of errors arc_read() may only return error code, but not properly report it via done and pio arguments. Lack of done calls may result in reference and/or memory leaks in higher level code. Lack of error reporting via pio may result in unnoticed errors there. For example, dbuf_read(), where dbuf_read_impl() ignores arc_read() return, relies completely on the pio mechanism and missed the errors. This patch makes arc_read() to always call done callback and always propagate errors to parent zio, if either is provided. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Brian Atkinson <[email protected]> Signed-off-by: Alexander Motin <[email protected]> Sponsored by: iXsystems, Inc.
1 parent 345f8be commit 48f376b

File tree

1 file changed

+16
-8
lines changed

1 file changed

+16
-8
lines changed

module/zfs/arc.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5943,6 +5943,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
59435943
(zio_flags & ZIO_FLAG_RAW_ENCRYPT) != 0;
59445944
boolean_t embedded_bp = !!BP_IS_EMBEDDED(bp);
59455945
boolean_t no_buf = *arc_flags & ARC_FLAG_NO_BUF;
5946+
arc_buf_t *buf = NULL;
59465947
int rc = 0;
59475948

59485949
ASSERT(!embedded_bp ||
@@ -5972,7 +5973,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
59725973
if (!zfs_blkptr_verify(spa, bp, zio_flags & ZIO_FLAG_CONFIG_WRITER,
59735974
BLK_VERIFY_LOG)) {
59745975
rc = SET_ERROR(ECKSUM);
5975-
goto out;
5976+
goto done;
59765977
}
59775978

59785979
if (!embedded_bp) {
@@ -5992,7 +5993,6 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
59925993
*/
59935994
if (hdr != NULL && HDR_HAS_L1HDR(hdr) && (HDR_HAS_RABD(hdr) ||
59945995
(hdr->b_l1hdr.b_pabd != NULL && !encrypted_read))) {
5995-
arc_buf_t *buf = NULL;
59965996
*arc_flags |= ARC_FLAG_CACHED;
59975997

59985998
if (HDR_IO_IN_PROGRESS(hdr)) {
@@ -6002,7 +6002,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
60026002
mutex_exit(hash_lock);
60036003
ARCSTAT_BUMP(arcstat_cached_only_in_progress);
60046004
rc = SET_ERROR(ENOENT);
6005-
goto out;
6005+
goto done;
60066006
}
60076007

60086008
ASSERT3P(head_zio, !=, NULL);
@@ -6130,9 +6130,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
61306130
ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr),
61316131
demand, prefetch, !HDR_ISTYPE_METADATA(hdr),
61326132
data, metadata, hits);
6133-
6134-
if (done)
6135-
done(NULL, zb, bp, buf, private);
6133+
goto done;
61366134
} else {
61376135
uint64_t lsize = BP_GET_LSIZE(bp);
61386136
uint64_t psize = BP_GET_PSIZE(bp);
@@ -6145,10 +6143,10 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
61456143
int alloc_flags = encrypted_read ? ARC_HDR_ALLOC_RDATA : 0;
61466144

61476145
if (*arc_flags & ARC_FLAG_CACHED_ONLY) {
6148-
rc = SET_ERROR(ENOENT);
61496146
if (hash_lock != NULL)
61506147
mutex_exit(hash_lock);
6151-
goto out;
6148+
rc = SET_ERROR(ENOENT);
6149+
goto done;
61526150
}
61536151

61546152
if (hdr == NULL) {
@@ -6474,6 +6472,16 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
64746472
spa_read_history_add(spa, zb, *arc_flags);
64756473
spl_fstrans_unmark(cookie);
64766474
return (rc);
6475+
6476+
done:
6477+
if (done)
6478+
done(NULL, zb, bp, buf, private);
6479+
if (pio && rc != 0) {
6480+
zio_t *zio = zio_null(pio, spa, NULL, NULL, NULL, zio_flags);
6481+
zio->io_error = rc;
6482+
zio_nowait(zio);
6483+
}
6484+
goto out;
64776485
}
64786486

64796487
arc_prune_t *

0 commit comments

Comments
 (0)