summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--module/zfs/range_tree.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/module/zfs/range_tree.c b/module/zfs/range_tree.c
index 1559605c2..2c0e4b860 100644
--- a/module/zfs/range_tree.c
+++ b/module/zfs/range_tree.c
@@ -251,9 +251,19 @@ range_tree_destroy(range_tree_t *rt)
void
range_tree_adjust_fill(range_tree_t *rt, range_seg_t *rs, int64_t delta)
{
- ASSERT3U(rs_get_fill(rs, rt) + delta, !=, 0);
- ASSERT3U(rs_get_fill(rs, rt) + delta, <=, rs_get_end(rs, rt) -
- rs_get_start(rs, rt));
+ if (delta < 0 && delta * -1 >= rs_get_fill(rs, rt)) {
+ zfs_panic_recover("zfs: attempting to decrease fill to or "
+ "below 0; probable double remove in segment [%llx:%llx]",
+ (longlong_t)rs_get_start(rs, rt),
+ (longlong_t)rs_get_end(rs, rt));
+ }
+ if (rs_get_fill(rs, rt) + delta > rs_get_end(rs, rt) -
+ rs_get_start(rs, rt)) {
+ zfs_panic_recover("zfs: attempting to increase fill beyond "
+ "max; probable double add in segment [%llx:%llx]",
+ (longlong_t)rs_get_start(rs, rt),
+ (longlong_t)rs_get_end(rs, rt));
+ }
if (rt->rt_ops != NULL && rt->rt_ops->rtop_remove != NULL)
rt->rt_ops->rtop_remove(rt, rs, rt->rt_arg);
@@ -290,10 +300,14 @@ range_tree_add_impl(void *arg, uint64_t start, uint64_t size, uint64_t fill)
* the normal code paths.
*/
if (rs != NULL) {
- ASSERT3U(rt->rt_gap, !=, 0);
+ if (gap == 0) {
+ zfs_panic_recover("zfs: adding existent segment to "
+ "range tree (offset=%llx size=%llx)",
+ (longlong_t)start, (longlong_t)size);
+ return;
+ }
uint64_t rstart = rs_get_start(rs, rt);
uint64_t rend = rs_get_end(rs, rt);
- ASSERT3U(gap, !=, 0);
if (rstart <= start && rend >= end) {
range_tree_adjust_fill(rt, rs, fill);
return;
@@ -431,7 +445,7 @@ range_tree_remove_impl(range_tree_t *rt, uint64_t start, uint64_t size,
/* Make sure we completely overlap with someone */
if (rs == NULL) {
zfs_panic_recover("zfs: removing nonexistent segment from "
- "range tree (offset=%llu size=%llu)",
+ "range tree (offset=%llx size=%llx)",
(longlong_t)start, (longlong_t)size);
return;
}
@@ -455,8 +469,8 @@ range_tree_remove_impl(range_tree_t *rt, uint64_t start, uint64_t size,
} else if (rs_get_start(rs, rt) != start ||
rs_get_end(rs, rt) != end) {
zfs_panic_recover("zfs: freeing partial segment of "
- "gap tree (offset=%llu size=%llu) of "
- "(offset=%llu size=%llu)",
+ "gap tree (offset=%llx size=%llx) of "
+ "(offset=%llx size=%llx)",
(longlong_t)start, (longlong_t)size,
(longlong_t)rs_get_start(rs, rt),
(longlong_t)rs_get_end(rs, rt) - rs_get_start(rs,