mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	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 <behlendorf1@llnl.gov> Reviewed-by: Brian Atkinson <batkinson@lanl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc.
This commit is contained in:
		
							parent
							
								
									345f8beb58
								
							
						
					
					
						commit
						48f376b0c5
					
				| @ -5943,6 +5943,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp, | |||||||
| 	    (zio_flags & ZIO_FLAG_RAW_ENCRYPT) != 0; | 	    (zio_flags & ZIO_FLAG_RAW_ENCRYPT) != 0; | ||||||
| 	boolean_t embedded_bp = !!BP_IS_EMBEDDED(bp); | 	boolean_t embedded_bp = !!BP_IS_EMBEDDED(bp); | ||||||
| 	boolean_t no_buf = *arc_flags & ARC_FLAG_NO_BUF; | 	boolean_t no_buf = *arc_flags & ARC_FLAG_NO_BUF; | ||||||
|  | 	arc_buf_t *buf = NULL; | ||||||
| 	int rc = 0; | 	int rc = 0; | ||||||
| 
 | 
 | ||||||
| 	ASSERT(!embedded_bp || | 	ASSERT(!embedded_bp || | ||||||
| @ -5972,7 +5973,7 @@ top: | |||||||
| 	if (!zfs_blkptr_verify(spa, bp, zio_flags & ZIO_FLAG_CONFIG_WRITER, | 	if (!zfs_blkptr_verify(spa, bp, zio_flags & ZIO_FLAG_CONFIG_WRITER, | ||||||
| 	    BLK_VERIFY_LOG)) { | 	    BLK_VERIFY_LOG)) { | ||||||
| 		rc = SET_ERROR(ECKSUM); | 		rc = SET_ERROR(ECKSUM); | ||||||
| 		goto out; | 		goto done; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!embedded_bp) { | 	if (!embedded_bp) { | ||||||
| @ -5992,7 +5993,6 @@ top: | |||||||
| 	 */ | 	 */ | ||||||
| 	if (hdr != NULL && HDR_HAS_L1HDR(hdr) && (HDR_HAS_RABD(hdr) || | 	if (hdr != NULL && HDR_HAS_L1HDR(hdr) && (HDR_HAS_RABD(hdr) || | ||||||
| 	    (hdr->b_l1hdr.b_pabd != NULL && !encrypted_read))) { | 	    (hdr->b_l1hdr.b_pabd != NULL && !encrypted_read))) { | ||||||
| 		arc_buf_t *buf = NULL; |  | ||||||
| 		*arc_flags |= ARC_FLAG_CACHED; | 		*arc_flags |= ARC_FLAG_CACHED; | ||||||
| 
 | 
 | ||||||
| 		if (HDR_IO_IN_PROGRESS(hdr)) { | 		if (HDR_IO_IN_PROGRESS(hdr)) { | ||||||
| @ -6002,7 +6002,7 @@ top: | |||||||
| 				mutex_exit(hash_lock); | 				mutex_exit(hash_lock); | ||||||
| 				ARCSTAT_BUMP(arcstat_cached_only_in_progress); | 				ARCSTAT_BUMP(arcstat_cached_only_in_progress); | ||||||
| 				rc = SET_ERROR(ENOENT); | 				rc = SET_ERROR(ENOENT); | ||||||
| 				goto out; | 				goto done; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			ASSERT3P(head_zio, !=, NULL); | 			ASSERT3P(head_zio, !=, NULL); | ||||||
| @ -6130,9 +6130,7 @@ top: | |||||||
| 		ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr), | 		ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr), | ||||||
| 		    demand, prefetch, !HDR_ISTYPE_METADATA(hdr), | 		    demand, prefetch, !HDR_ISTYPE_METADATA(hdr), | ||||||
| 		    data, metadata, hits); | 		    data, metadata, hits); | ||||||
| 
 | 		goto done; | ||||||
| 		if (done) |  | ||||||
| 			done(NULL, zb, bp, buf, private); |  | ||||||
| 	} else { | 	} else { | ||||||
| 		uint64_t lsize = BP_GET_LSIZE(bp); | 		uint64_t lsize = BP_GET_LSIZE(bp); | ||||||
| 		uint64_t psize = BP_GET_PSIZE(bp); | 		uint64_t psize = BP_GET_PSIZE(bp); | ||||||
| @ -6145,10 +6143,10 @@ top: | |||||||
| 		int alloc_flags = encrypted_read ? ARC_HDR_ALLOC_RDATA : 0; | 		int alloc_flags = encrypted_read ? ARC_HDR_ALLOC_RDATA : 0; | ||||||
| 
 | 
 | ||||||
| 		if (*arc_flags & ARC_FLAG_CACHED_ONLY) { | 		if (*arc_flags & ARC_FLAG_CACHED_ONLY) { | ||||||
| 			rc = SET_ERROR(ENOENT); |  | ||||||
| 			if (hash_lock != NULL) | 			if (hash_lock != NULL) | ||||||
| 				mutex_exit(hash_lock); | 				mutex_exit(hash_lock); | ||||||
| 			goto out; | 			rc = SET_ERROR(ENOENT); | ||||||
|  | 			goto done; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (hdr == NULL) { | 		if (hdr == NULL) { | ||||||
| @ -6474,6 +6472,16 @@ out: | |||||||
| 		spa_read_history_add(spa, zb, *arc_flags); | 		spa_read_history_add(spa, zb, *arc_flags); | ||||||
| 	spl_fstrans_unmark(cookie); | 	spl_fstrans_unmark(cookie); | ||||||
| 	return (rc); | 	return (rc); | ||||||
|  | 
 | ||||||
|  | done: | ||||||
|  | 	if (done) | ||||||
|  | 		done(NULL, zb, bp, buf, private); | ||||||
|  | 	if (pio && rc != 0) { | ||||||
|  | 		zio_t *zio = zio_null(pio, spa, NULL, NULL, NULL, zio_flags); | ||||||
|  | 		zio->io_error = rc; | ||||||
|  | 		zio_nowait(zio); | ||||||
|  | 	} | ||||||
|  | 	goto out; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| arc_prune_t * | arc_prune_t * | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Alexander Motin
						Alexander Motin