xref: /freebsd/sys/kern/subr_rangeset.c (revision 4d846d260e2b9a3d4d0a701462568268cbfe7a5b)
11809ef78SKonstantin Belousov /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31809ef78SKonstantin Belousov  *
41809ef78SKonstantin Belousov  * Copyright (c) 2019 The FreeBSD Foundation
51809ef78SKonstantin Belousov  *
61809ef78SKonstantin Belousov  * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
71809ef78SKonstantin Belousov  * under sponsorship from the FreeBSD Foundation.
81809ef78SKonstantin Belousov  *
91809ef78SKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
101809ef78SKonstantin Belousov  * modification, are permitted provided that the following conditions
111809ef78SKonstantin Belousov  * are met:
121809ef78SKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
131809ef78SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
141809ef78SKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
151809ef78SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
161809ef78SKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
171809ef78SKonstantin Belousov  *
181809ef78SKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
191809ef78SKonstantin Belousov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
201809ef78SKonstantin Belousov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
211809ef78SKonstantin Belousov  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
221809ef78SKonstantin Belousov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
231809ef78SKonstantin Belousov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
241809ef78SKonstantin Belousov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
251809ef78SKonstantin Belousov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261809ef78SKonstantin Belousov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
271809ef78SKonstantin Belousov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
281809ef78SKonstantin Belousov  * SUCH DAMAGE.
291809ef78SKonstantin Belousov  */
301809ef78SKonstantin Belousov 
311809ef78SKonstantin Belousov #include <sys/cdefs.h>
321809ef78SKonstantin Belousov __FBSDID("$FreeBSD$");
331809ef78SKonstantin Belousov 
341809ef78SKonstantin Belousov #include <sys/param.h>
351809ef78SKonstantin Belousov #include <sys/kernel.h>
361809ef78SKonstantin Belousov #include <sys/lock.h>
371809ef78SKonstantin Belousov #include <sys/pctrie.h>
381809ef78SKonstantin Belousov #include <sys/rangeset.h>
391809ef78SKonstantin Belousov #include <vm/uma.h>
401809ef78SKonstantin Belousov 
411809ef78SKonstantin Belousov #ifdef DIAGNOSTIC
421809ef78SKonstantin Belousov static void rangeset_check(struct rangeset *rs);
431809ef78SKonstantin Belousov #else
441809ef78SKonstantin Belousov #define	rangeset_check(rs)
451809ef78SKonstantin Belousov #endif
461809ef78SKonstantin Belousov 
471809ef78SKonstantin Belousov static uma_zone_t rs_node_zone;
481809ef78SKonstantin Belousov 
491809ef78SKonstantin Belousov static void
501809ef78SKonstantin Belousov rs_rangeset_init(void *arg __unused)
511809ef78SKonstantin Belousov {
521809ef78SKonstantin Belousov 
531809ef78SKonstantin Belousov 	rs_node_zone = uma_zcreate("rangeset pctrie nodes",
541809ef78SKonstantin Belousov 	    pctrie_node_size(), NULL, NULL, pctrie_zone_init, NULL,
551809ef78SKonstantin Belousov 	    UMA_ALIGN_PTR, 0);
561809ef78SKonstantin Belousov }
571809ef78SKonstantin Belousov SYSINIT(rs, SI_SUB_LOCK, SI_ORDER_ANY, rs_rangeset_init, NULL);
581809ef78SKonstantin Belousov 
591809ef78SKonstantin Belousov static void *
601809ef78SKonstantin Belousov rs_node_alloc(struct pctrie *ptree)
611809ef78SKonstantin Belousov {
621809ef78SKonstantin Belousov 	struct rangeset *rs;
631809ef78SKonstantin Belousov 
641809ef78SKonstantin Belousov 	rs = __containerof(ptree, struct rangeset, rs_trie);
651809ef78SKonstantin Belousov 	return (uma_zalloc(rs_node_zone, rs->rs_alloc_flags));
661809ef78SKonstantin Belousov }
671809ef78SKonstantin Belousov 
681809ef78SKonstantin Belousov static void
691809ef78SKonstantin Belousov rs_node_free(struct pctrie *ptree __unused, void *node)
701809ef78SKonstantin Belousov {
711809ef78SKonstantin Belousov 
721809ef78SKonstantin Belousov 	uma_zfree(rs_node_zone, node);
731809ef78SKonstantin Belousov }
741809ef78SKonstantin Belousov 
751809ef78SKonstantin Belousov void
761809ef78SKonstantin Belousov rangeset_init(struct rangeset *rs, rs_dup_data_t dup_data,
771809ef78SKonstantin Belousov     rs_free_data_t free_data, void *data_ctx, u_int alloc_flags)
781809ef78SKonstantin Belousov {
791809ef78SKonstantin Belousov 
801809ef78SKonstantin Belousov 	pctrie_init(&rs->rs_trie);
811809ef78SKonstantin Belousov 	rs->rs_dup_data = dup_data;
821809ef78SKonstantin Belousov 	rs->rs_free_data = free_data;
831809ef78SKonstantin Belousov 	rs->rs_data_ctx = data_ctx;
841809ef78SKonstantin Belousov 	rs->rs_alloc_flags = alloc_flags;
851809ef78SKonstantin Belousov }
861809ef78SKonstantin Belousov 
871809ef78SKonstantin Belousov void
881809ef78SKonstantin Belousov rangeset_fini(struct rangeset *rs)
891809ef78SKonstantin Belousov {
901809ef78SKonstantin Belousov 
911809ef78SKonstantin Belousov 	rangeset_check(rs);
921809ef78SKonstantin Belousov 	rangeset_remove_all(rs);
931809ef78SKonstantin Belousov }
941809ef78SKonstantin Belousov 
951809ef78SKonstantin Belousov bool
961809ef78SKonstantin Belousov rangeset_check_empty(struct rangeset *rs, uint64_t start, uint64_t end)
971809ef78SKonstantin Belousov {
981809ef78SKonstantin Belousov 	struct rs_el *r;
991809ef78SKonstantin Belousov 	uint64_t *r1;
1001809ef78SKonstantin Belousov 
1011809ef78SKonstantin Belousov 	rangeset_check(rs);
1021809ef78SKonstantin Belousov 	r1 = pctrie_lookup_le(&rs->rs_trie, end);
1031809ef78SKonstantin Belousov 	if (r1 != NULL) {
1041809ef78SKonstantin Belousov 		r = __containerof(r1, struct rs_el, re_start);
1051809ef78SKonstantin Belousov 		if (r->re_end > start)
1061809ef78SKonstantin Belousov 			return (false);
1071809ef78SKonstantin Belousov 	}
1081809ef78SKonstantin Belousov 	return (true);
1091809ef78SKonstantin Belousov }
1101809ef78SKonstantin Belousov 
1111809ef78SKonstantin Belousov int
1121809ef78SKonstantin Belousov rangeset_insert(struct rangeset *rs, uint64_t start, uint64_t end,
1131809ef78SKonstantin Belousov     void *data)
1141809ef78SKonstantin Belousov {
1151809ef78SKonstantin Belousov 	struct rs_el *r;
1161809ef78SKonstantin Belousov 	int error;
1171809ef78SKonstantin Belousov 
1181809ef78SKonstantin Belousov 	rangeset_check(rs);
1191809ef78SKonstantin Belousov 	error = rangeset_remove(rs, start, end);
1201809ef78SKonstantin Belousov 	if (error != 0)
1211809ef78SKonstantin Belousov 		return (error);
1221809ef78SKonstantin Belousov 	r = data;
1231809ef78SKonstantin Belousov 	r->re_start = start;
1241809ef78SKonstantin Belousov 	r->re_end = end;
1251809ef78SKonstantin Belousov 	error = pctrie_insert(&rs->rs_trie, &r->re_start, rs_node_alloc);
1261809ef78SKonstantin Belousov 	rangeset_check(rs);
1271809ef78SKonstantin Belousov 	return (error);
1281809ef78SKonstantin Belousov }
1291809ef78SKonstantin Belousov 
1301809ef78SKonstantin Belousov int
1311809ef78SKonstantin Belousov rangeset_remove_pred(struct rangeset *rs, uint64_t start, uint64_t end,
1321809ef78SKonstantin Belousov     rs_pred_t pred)
1331809ef78SKonstantin Belousov {
1341809ef78SKonstantin Belousov 	struct rs_el *r, *rn;
1351809ef78SKonstantin Belousov 	uint64_t *r1;
1361809ef78SKonstantin Belousov 	int error;
1371809ef78SKonstantin Belousov 
1381809ef78SKonstantin Belousov 	rangeset_check(rs);
1391809ef78SKonstantin Belousov 	error = 0;
1401809ef78SKonstantin Belousov 	for (; end > 0 && start < end;) {
1411809ef78SKonstantin Belousov 		r1 = pctrie_lookup_le(&rs->rs_trie, end - 1);
1421809ef78SKonstantin Belousov 		if (r1 == NULL)
1431809ef78SKonstantin Belousov 			break;
1441809ef78SKonstantin Belousov 		r = __containerof(r1, struct rs_el, re_start);
1451809ef78SKonstantin Belousov 
1461809ef78SKonstantin Belousov 		/*
1471809ef78SKonstantin Belousov 		 * ------============================--|-------|----
1481809ef78SKonstantin Belousov 		 *	 rs    	       	       	   re  s       e
1491809ef78SKonstantin Belousov 		 */
1501809ef78SKonstantin Belousov 		if (r->re_end <= start)
1511809ef78SKonstantin Belousov 			break;
1521809ef78SKonstantin Belousov 
1531809ef78SKonstantin Belousov 		if (r->re_end <= end) {
1541809ef78SKonstantin Belousov 			if (r->re_start < start) {
1551809ef78SKonstantin Belousov 				/*
1561809ef78SKonstantin Belousov 				 * ------========|==============-------|----
1571809ef78SKonstantin Belousov 				 *	 rs    	 s     	      re       e
1581809ef78SKonstantin Belousov 				 */
1591809ef78SKonstantin Belousov 				if (pred(rs->rs_data_ctx, r))
1601809ef78SKonstantin Belousov 					r->re_end = start;
1611809ef78SKonstantin Belousov 				break;
1621809ef78SKonstantin Belousov 			}
1631809ef78SKonstantin Belousov 
1641809ef78SKonstantin Belousov 			/*
1651809ef78SKonstantin Belousov 			 * ------|--------===================----------|----
1661809ef78SKonstantin Belousov 			 *	 s    	  rs   	       	   re          e
1671809ef78SKonstantin Belousov 			 */
1681809ef78SKonstantin Belousov 			end = r->re_start;
1691809ef78SKonstantin Belousov 			if (pred(rs->rs_data_ctx, r)) {
1701809ef78SKonstantin Belousov 				pctrie_remove(&rs->rs_trie, r->re_start,
1711809ef78SKonstantin Belousov 				    rs_node_free);
1721809ef78SKonstantin Belousov 				rs->rs_free_data(rs->rs_data_ctx, r);
1731809ef78SKonstantin Belousov 			}
1741809ef78SKonstantin Belousov 			continue;
1751809ef78SKonstantin Belousov 		}
1761809ef78SKonstantin Belousov 
1771809ef78SKonstantin Belousov 		/*
1781809ef78SKonstantin Belousov 		 * ------|--------====================|==========----
1791809ef78SKonstantin Belousov 		 *	 s    	  rs   	       	      e         re
1801809ef78SKonstantin Belousov 		 */
1811809ef78SKonstantin Belousov 		if (r->re_start >= start) {
1821809ef78SKonstantin Belousov 			if (pred(rs->rs_data_ctx, r)) {
1831809ef78SKonstantin Belousov 				pctrie_remove(&rs->rs_trie, r->re_start,
1841809ef78SKonstantin Belousov 				    rs_node_free);
1851809ef78SKonstantin Belousov 				r->re_start = end;
1861809ef78SKonstantin Belousov 				error = pctrie_insert(&rs->rs_trie,
1871809ef78SKonstantin Belousov 				    &r->re_start, rs_node_alloc);
1881809ef78SKonstantin Belousov 				/*
1891809ef78SKonstantin Belousov 				 * The insert above must succeed
1901809ef78SKonstantin Belousov 				 * because rs_node zone is marked
1911809ef78SKonstantin Belousov 				 * nofree and we freed one element
1921809ef78SKonstantin Belousov 				 * just before.
1931809ef78SKonstantin Belousov 				 */
1941809ef78SKonstantin Belousov 				MPASS(error == 0);
1951809ef78SKonstantin Belousov 			} else {
1961809ef78SKonstantin Belousov 				end = r->re_start;
1971809ef78SKonstantin Belousov 			}
1981809ef78SKonstantin Belousov 			continue;
1991809ef78SKonstantin Belousov 		}
2001809ef78SKonstantin Belousov 
2011809ef78SKonstantin Belousov 		/*
2021809ef78SKonstantin Belousov 		 * ------=========|===================|==========----
2031809ef78SKonstantin Belousov 		 *	 rs   	  s    	       	      e         re
2041809ef78SKonstantin Belousov 		 */
2051809ef78SKonstantin Belousov 		if (pred(rs->rs_data_ctx, r)) {
2061809ef78SKonstantin Belousov 			/*
2071809ef78SKonstantin Belousov 			 * Split.  Can only happen once, and then if
2081809ef78SKonstantin Belousov 			 * any allocation fails, the rangeset is kept
2091809ef78SKonstantin Belousov 			 * intact.
2101809ef78SKonstantin Belousov 			 */
2111809ef78SKonstantin Belousov 			rn = rs->rs_dup_data(rs->rs_data_ctx, r);
2121809ef78SKonstantin Belousov 			if (rn == NULL) {
2131809ef78SKonstantin Belousov 				error = ENOMEM;
2141809ef78SKonstantin Belousov 				break;
2151809ef78SKonstantin Belousov 			}
2161809ef78SKonstantin Belousov 			rn->re_start = end;
2171809ef78SKonstantin Belousov 			rn->re_end = r->re_end;
2181809ef78SKonstantin Belousov 			error = pctrie_insert(&rs->rs_trie, &rn->re_start,
2191809ef78SKonstantin Belousov 			    rs_node_alloc);
2201809ef78SKonstantin Belousov 			if (error != 0) {
2211809ef78SKonstantin Belousov 				rs->rs_free_data(rs->rs_data_ctx, rn);
2221809ef78SKonstantin Belousov 				break;
2231809ef78SKonstantin Belousov 			}
2241809ef78SKonstantin Belousov 			r->re_end = start;
2251809ef78SKonstantin Belousov 		}
2261809ef78SKonstantin Belousov 		break;
2271809ef78SKonstantin Belousov 	}
2281809ef78SKonstantin Belousov 	rangeset_check(rs);
2291809ef78SKonstantin Belousov 	return (error);
2301809ef78SKonstantin Belousov }
2311809ef78SKonstantin Belousov 
2321809ef78SKonstantin Belousov static bool
2331809ef78SKonstantin Belousov rangeset_true_pred(void *ctx __unused, void *r __unused)
2341809ef78SKonstantin Belousov {
2351809ef78SKonstantin Belousov 
2361809ef78SKonstantin Belousov 	return (true);
2371809ef78SKonstantin Belousov }
2381809ef78SKonstantin Belousov 
2391809ef78SKonstantin Belousov int
2401809ef78SKonstantin Belousov rangeset_remove(struct rangeset *rs, uint64_t start, uint64_t end)
2411809ef78SKonstantin Belousov {
2421809ef78SKonstantin Belousov 
2431809ef78SKonstantin Belousov 	return (rangeset_remove_pred(rs, start, end, rangeset_true_pred));
2441809ef78SKonstantin Belousov }
2451809ef78SKonstantin Belousov 
2461809ef78SKonstantin Belousov void
2471809ef78SKonstantin Belousov rangeset_remove_all(struct rangeset *rs)
2481809ef78SKonstantin Belousov {
2491809ef78SKonstantin Belousov 	struct rs_el *r;
2501809ef78SKonstantin Belousov 	uint64_t *r1;
2511809ef78SKonstantin Belousov 
2521809ef78SKonstantin Belousov 	for (;;) {
2531809ef78SKonstantin Belousov 		r1 = pctrie_lookup_ge(&rs->rs_trie, 0);
2541809ef78SKonstantin Belousov 		if (r1 == NULL)
2551809ef78SKonstantin Belousov 			break;
2561809ef78SKonstantin Belousov 		r = __containerof(r1, struct rs_el, re_start);
2571809ef78SKonstantin Belousov 		pctrie_remove(&rs->rs_trie, r->re_start, rs_node_free);
2581809ef78SKonstantin Belousov 		rs->rs_free_data(rs->rs_data_ctx, r);
2591809ef78SKonstantin Belousov 	}
2601809ef78SKonstantin Belousov }
2611809ef78SKonstantin Belousov 
2621809ef78SKonstantin Belousov void *
2631809ef78SKonstantin Belousov rangeset_lookup(struct rangeset *rs, uint64_t place)
2641809ef78SKonstantin Belousov {
2651809ef78SKonstantin Belousov 	struct rs_el *r;
2661809ef78SKonstantin Belousov 	uint64_t *r1;
2671809ef78SKonstantin Belousov 
2681809ef78SKonstantin Belousov 	rangeset_check(rs);
2691809ef78SKonstantin Belousov 	r1 = pctrie_lookup_le(&rs->rs_trie, place);
2701809ef78SKonstantin Belousov 	if (r1 == NULL)
2711809ef78SKonstantin Belousov 		return (NULL);
2721809ef78SKonstantin Belousov 	r = __containerof(r1, struct rs_el, re_start);
2731809ef78SKonstantin Belousov 	if (r->re_end <= place)
2741809ef78SKonstantin Belousov 		return (NULL);
2751809ef78SKonstantin Belousov 	return (r);
2761809ef78SKonstantin Belousov }
2771809ef78SKonstantin Belousov 
2781809ef78SKonstantin Belousov int
2791809ef78SKonstantin Belousov rangeset_copy(struct rangeset *dst_rs, struct rangeset *src_rs)
2801809ef78SKonstantin Belousov {
2811809ef78SKonstantin Belousov 	struct rs_el *src_r, *dst_r;
2821809ef78SKonstantin Belousov 	uint64_t cursor, *r1;
2831809ef78SKonstantin Belousov 	int error;
2841809ef78SKonstantin Belousov 
2851809ef78SKonstantin Belousov 	MPASS(pctrie_is_empty(&dst_rs->rs_trie));
2861809ef78SKonstantin Belousov 	rangeset_check(src_rs);
2871809ef78SKonstantin Belousov 	MPASS(dst_rs->rs_dup_data == src_rs->rs_dup_data);
2881809ef78SKonstantin Belousov 
2891809ef78SKonstantin Belousov 	error = 0;
2901809ef78SKonstantin Belousov 	for (cursor = 0;; cursor = src_r->re_start + 1) {
2911809ef78SKonstantin Belousov 		r1 = pctrie_lookup_ge(&src_rs->rs_trie, cursor);
2921809ef78SKonstantin Belousov 		if (r1 == NULL)
2931809ef78SKonstantin Belousov 			break;
2941809ef78SKonstantin Belousov 		src_r = __containerof(r1, struct rs_el, re_start);
2951809ef78SKonstantin Belousov 		dst_r = dst_rs->rs_dup_data(dst_rs->rs_data_ctx, src_r);
2961809ef78SKonstantin Belousov 		if (dst_r == NULL) {
2971809ef78SKonstantin Belousov 			error = ENOMEM;
2981809ef78SKonstantin Belousov 			break;
2991809ef78SKonstantin Belousov 		}
3001809ef78SKonstantin Belousov 		error = pctrie_insert(&dst_rs->rs_trie, &dst_r->re_start,
3011809ef78SKonstantin Belousov 		    rs_node_alloc);
3021809ef78SKonstantin Belousov 		if (error != 0)
3031809ef78SKonstantin Belousov 			break;
3041809ef78SKonstantin Belousov 	}
3051809ef78SKonstantin Belousov 	if (error != 0)
3061809ef78SKonstantin Belousov 		rangeset_remove_all(dst_rs);
3071809ef78SKonstantin Belousov 	return (error);
3081809ef78SKonstantin Belousov }
3091809ef78SKonstantin Belousov 
3101809ef78SKonstantin Belousov #ifdef DIAGNOSTIC
3111809ef78SKonstantin Belousov static void
3121809ef78SKonstantin Belousov rangeset_check(struct rangeset *rs)
3131809ef78SKonstantin Belousov {
3141809ef78SKonstantin Belousov 	struct rs_el *r, *rp;
3151809ef78SKonstantin Belousov 	uint64_t cursor, *r1;
3161809ef78SKonstantin Belousov 
3171809ef78SKonstantin Belousov 	for (cursor = 0, rp = NULL;; cursor = r->re_start + 1, rp = r) {
3181809ef78SKonstantin Belousov 		r1 = pctrie_lookup_ge(&rs->rs_trie, cursor);
3191809ef78SKonstantin Belousov 		if (r1 == NULL)
3201809ef78SKonstantin Belousov 			break;
3211809ef78SKonstantin Belousov 		r = __containerof(r1, struct rs_el, re_start);
3221809ef78SKonstantin Belousov 		KASSERT(r->re_start < r->re_end,
3231809ef78SKonstantin Belousov 		    ("invalid interval rs %p elem %p (%#jx, %#jx)",
3241809ef78SKonstantin Belousov 		    rs, r, (uintmax_t)r->re_start,  (uintmax_t)r->re_end));
3251809ef78SKonstantin Belousov 		if (rp != NULL) {
3261809ef78SKonstantin Belousov 			KASSERT(rp->re_end <= r->re_start,
3271809ef78SKonstantin Belousov 			    ("non-ascending neighbors rs %p "
3281809ef78SKonstantin Belousov 			    "prev elem %p (%#jx, %#jx) elem %p (%#jx, %#jx)",
3291809ef78SKonstantin Belousov 			    rs, rp,  (uintmax_t)rp->re_start,
3301809ef78SKonstantin Belousov 			    (uintmax_t)rp->re_end, r,  (uintmax_t)r->re_start,
3311809ef78SKonstantin Belousov 			    (uintmax_t)r->re_end));
3321809ef78SKonstantin Belousov 		}
3331809ef78SKonstantin Belousov 	}
3341809ef78SKonstantin Belousov }
3351809ef78SKonstantin Belousov #endif
3361809ef78SKonstantin Belousov 
3371809ef78SKonstantin Belousov #include "opt_ddb.h"
3381809ef78SKonstantin Belousov #ifdef DDB
3391809ef78SKonstantin Belousov #include <sys/kernel.h>
3401809ef78SKonstantin Belousov #include <ddb/ddb.h>
3411809ef78SKonstantin Belousov 
3421809ef78SKonstantin Belousov DB_SHOW_COMMAND(rangeset, rangeset_show_fn)
3431809ef78SKonstantin Belousov {
3441809ef78SKonstantin Belousov 	struct rangeset *rs;
3451809ef78SKonstantin Belousov 	struct rs_el *r;
3461809ef78SKonstantin Belousov 	uint64_t cursor, *r1;
3471809ef78SKonstantin Belousov 
3481809ef78SKonstantin Belousov 	if (!have_addr) {
3491809ef78SKonstantin Belousov 		db_printf("show rangeset addr\n");
3501809ef78SKonstantin Belousov 		return;
3511809ef78SKonstantin Belousov 	}
3521809ef78SKonstantin Belousov 
3531809ef78SKonstantin Belousov 	rs = (struct rangeset *)addr;
3541809ef78SKonstantin Belousov 	db_printf("rangeset %p\n", rs);
3551809ef78SKonstantin Belousov 	for (cursor = 0;; cursor = r->re_start + 1) {
3561809ef78SKonstantin Belousov 		r1 = pctrie_lookup_ge(&rs->rs_trie, cursor);
3571809ef78SKonstantin Belousov 		if (r1 == NULL)
3581809ef78SKonstantin Belousov 			break;
3591809ef78SKonstantin Belousov 		r = __containerof(r1, struct rs_el, re_start);
3601809ef78SKonstantin Belousov 		db_printf("  el %p start %#jx end %#jx\n",
3611809ef78SKonstantin Belousov 		    r, r->re_start, r->re_end);
3621809ef78SKonstantin Belousov 	}
3631809ef78SKonstantin Belousov }
3641809ef78SKonstantin Belousov #endif
365