On FreeBSD ERESTART and TRAVERSE_VISIT_NO_CHILDREN have the same value of -1.
Both can be returned from traversal callbacks.
TRAVERSE_VISIT_NO_CHILDREN has special handling within the traversal code.
So, it's possible that ERESTART returned from a callback like dsl_scan_free_block_cb
would be handled as TRAVERSE_VISIT_NO_CHILDREN.
Describe how to reproduce the problem
I do not have a clear demonstrator but I suspect that the problem could be triggered
when destroying a large dataset such that dsl_scan_free_block_cb would have to return
ERESTART .
As a result traverse_dnode could skip remaining blocks under a dnode where ERESTART
is triggered.
Those blocks would be leaked.
Possible solution
Change value of TRAVERSE_VISIT_NO_CHILDREN to something even "more magic" to avoid
conflict with low numbered negative return values used in FreeBSD
(defined in errno.h).
For example, a value of -100 should work fine.
System information
Describe the problem you're observing
On FreeBSD
ERESTART
andTRAVERSE_VISIT_NO_CHILDREN
have the same value of -1. Both can be returned from traversal callbacks.TRAVERSE_VISIT_NO_CHILDREN
has special handling within the traversal code. So, it's possible thatERESTART
returned from a callback likedsl_scan_free_block_cb
would be handled asTRAVERSE_VISIT_NO_CHILDREN
.Describe how to reproduce the problem
I do not have a clear demonstrator but I suspect that the problem could be triggered when destroying a large dataset such that
dsl_scan_free_block_cb
would have to returnERESTART
.As a result
traverse_dnode
could skip remaining blocks under a dnode whereERESTART
is triggered. Those blocks would be leaked.Possible solution
Change value of
TRAVERSE_VISIT_NO_CHILDREN
to something even "more magic" to avoid conflict with low numbered negative return values used in FreeBSD (defined in errno.h). For example, a value of -100 should work fine.