18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2011 STRATO AG 48c2ecf20Sopenharmony_ci * written by Arne Jansen <sensille@gmx.net> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/slab.h> 88c2ecf20Sopenharmony_ci#include "ulist.h" 98c2ecf20Sopenharmony_ci#include "ctree.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* 128c2ecf20Sopenharmony_ci * ulist is a generic data structure to hold a collection of unique u64 138c2ecf20Sopenharmony_ci * values. The only operations it supports is adding to the list and 148c2ecf20Sopenharmony_ci * enumerating it. 158c2ecf20Sopenharmony_ci * It is possible to store an auxiliary value along with the key. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * A sample usage for ulists is the enumeration of directed graphs without 188c2ecf20Sopenharmony_ci * visiting a node twice. The pseudo-code could look like this: 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * ulist = ulist_alloc(); 218c2ecf20Sopenharmony_ci * ulist_add(ulist, root); 228c2ecf20Sopenharmony_ci * ULIST_ITER_INIT(&uiter); 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * while ((elem = ulist_next(ulist, &uiter)) { 258c2ecf20Sopenharmony_ci * for (all child nodes n in elem) 268c2ecf20Sopenharmony_ci * ulist_add(ulist, n); 278c2ecf20Sopenharmony_ci * do something useful with the node; 288c2ecf20Sopenharmony_ci * } 298c2ecf20Sopenharmony_ci * ulist_free(ulist); 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * This assumes the graph nodes are addressable by u64. This stems from the 328c2ecf20Sopenharmony_ci * usage for tree enumeration in btrfs, where the logical addresses are 338c2ecf20Sopenharmony_ci * 64 bit. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci * It is also useful for tree enumeration which could be done elegantly 368c2ecf20Sopenharmony_ci * recursively, but is not possible due to kernel stack limitations. The 378c2ecf20Sopenharmony_ci * loop would be similar to the above. 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/** 418c2ecf20Sopenharmony_ci * ulist_init - freshly initialize a ulist 428c2ecf20Sopenharmony_ci * @ulist: the ulist to initialize 438c2ecf20Sopenharmony_ci * 448c2ecf20Sopenharmony_ci * Note: don't use this function to init an already used ulist, use 458c2ecf20Sopenharmony_ci * ulist_reinit instead. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_civoid ulist_init(struct ulist *ulist) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ulist->nodes); 508c2ecf20Sopenharmony_ci ulist->root = RB_ROOT; 518c2ecf20Sopenharmony_ci ulist->nnodes = 0; 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/** 558c2ecf20Sopenharmony_ci * ulist_release - free up additionally allocated memory for the ulist 568c2ecf20Sopenharmony_ci * @ulist: the ulist from which to free the additional memory 578c2ecf20Sopenharmony_ci * 588c2ecf20Sopenharmony_ci * This is useful in cases where the base 'struct ulist' has been statically 598c2ecf20Sopenharmony_ci * allocated. 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_civoid ulist_release(struct ulist *ulist) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct ulist_node *node; 648c2ecf20Sopenharmony_ci struct ulist_node *next; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci list_for_each_entry_safe(node, next, &ulist->nodes, list) { 678c2ecf20Sopenharmony_ci kfree(node); 688c2ecf20Sopenharmony_ci } 698c2ecf20Sopenharmony_ci ulist->root = RB_ROOT; 708c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ulist->nodes); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/** 748c2ecf20Sopenharmony_ci * ulist_reinit - prepare a ulist for reuse 758c2ecf20Sopenharmony_ci * @ulist: ulist to be reused 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * Free up all additional memory allocated for the list elements and reinit 788c2ecf20Sopenharmony_ci * the ulist. 798c2ecf20Sopenharmony_ci */ 808c2ecf20Sopenharmony_civoid ulist_reinit(struct ulist *ulist) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci ulist_release(ulist); 838c2ecf20Sopenharmony_ci ulist_init(ulist); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci/** 878c2ecf20Sopenharmony_ci * ulist_alloc - dynamically allocate a ulist 888c2ecf20Sopenharmony_ci * @gfp_mask: allocation flags to for base allocation 898c2ecf20Sopenharmony_ci * 908c2ecf20Sopenharmony_ci * The allocated ulist will be returned in an initialized state. 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_cistruct ulist *ulist_alloc(gfp_t gfp_mask) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci struct ulist *ulist = kmalloc(sizeof(*ulist), gfp_mask); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (!ulist) 978c2ecf20Sopenharmony_ci return NULL; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci ulist_init(ulist); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci return ulist; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/** 1058c2ecf20Sopenharmony_ci * ulist_free - free dynamically allocated ulist 1068c2ecf20Sopenharmony_ci * @ulist: ulist to free 1078c2ecf20Sopenharmony_ci * 1088c2ecf20Sopenharmony_ci * It is not necessary to call ulist_release before. 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_civoid ulist_free(struct ulist *ulist) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci if (!ulist) 1138c2ecf20Sopenharmony_ci return; 1148c2ecf20Sopenharmony_ci ulist_release(ulist); 1158c2ecf20Sopenharmony_ci kfree(ulist); 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic struct ulist_node *ulist_rbtree_search(struct ulist *ulist, u64 val) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci struct rb_node *n = ulist->root.rb_node; 1218c2ecf20Sopenharmony_ci struct ulist_node *u = NULL; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci while (n) { 1248c2ecf20Sopenharmony_ci u = rb_entry(n, struct ulist_node, rb_node); 1258c2ecf20Sopenharmony_ci if (u->val < val) 1268c2ecf20Sopenharmony_ci n = n->rb_right; 1278c2ecf20Sopenharmony_ci else if (u->val > val) 1288c2ecf20Sopenharmony_ci n = n->rb_left; 1298c2ecf20Sopenharmony_ci else 1308c2ecf20Sopenharmony_ci return u; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci return NULL; 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic void ulist_rbtree_erase(struct ulist *ulist, struct ulist_node *node) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci rb_erase(&node->rb_node, &ulist->root); 1388c2ecf20Sopenharmony_ci list_del(&node->list); 1398c2ecf20Sopenharmony_ci kfree(node); 1408c2ecf20Sopenharmony_ci BUG_ON(ulist->nnodes == 0); 1418c2ecf20Sopenharmony_ci ulist->nnodes--; 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic int ulist_rbtree_insert(struct ulist *ulist, struct ulist_node *ins) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci struct rb_node **p = &ulist->root.rb_node; 1478c2ecf20Sopenharmony_ci struct rb_node *parent = NULL; 1488c2ecf20Sopenharmony_ci struct ulist_node *cur = NULL; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci while (*p) { 1518c2ecf20Sopenharmony_ci parent = *p; 1528c2ecf20Sopenharmony_ci cur = rb_entry(parent, struct ulist_node, rb_node); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if (cur->val < ins->val) 1558c2ecf20Sopenharmony_ci p = &(*p)->rb_right; 1568c2ecf20Sopenharmony_ci else if (cur->val > ins->val) 1578c2ecf20Sopenharmony_ci p = &(*p)->rb_left; 1588c2ecf20Sopenharmony_ci else 1598c2ecf20Sopenharmony_ci return -EEXIST; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci rb_link_node(&ins->rb_node, parent, p); 1628c2ecf20Sopenharmony_ci rb_insert_color(&ins->rb_node, &ulist->root); 1638c2ecf20Sopenharmony_ci return 0; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/** 1678c2ecf20Sopenharmony_ci * ulist_add - add an element to the ulist 1688c2ecf20Sopenharmony_ci * @ulist: ulist to add the element to 1698c2ecf20Sopenharmony_ci * @val: value to add to ulist 1708c2ecf20Sopenharmony_ci * @aux: auxiliary value to store along with val 1718c2ecf20Sopenharmony_ci * @gfp_mask: flags to use for allocation 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * Note: locking must be provided by the caller. In case of rwlocks write 1748c2ecf20Sopenharmony_ci * locking is needed 1758c2ecf20Sopenharmony_ci * 1768c2ecf20Sopenharmony_ci * Add an element to a ulist. The @val will only be added if it doesn't 1778c2ecf20Sopenharmony_ci * already exist. If it is added, the auxiliary value @aux is stored along with 1788c2ecf20Sopenharmony_ci * it. In case @val already exists in the ulist, @aux is ignored, even if 1798c2ecf20Sopenharmony_ci * it differs from the already stored value. 1808c2ecf20Sopenharmony_ci * 1818c2ecf20Sopenharmony_ci * ulist_add returns 0 if @val already exists in ulist and 1 if @val has been 1828c2ecf20Sopenharmony_ci * inserted. 1838c2ecf20Sopenharmony_ci * In case of allocation failure -ENOMEM is returned and the ulist stays 1848c2ecf20Sopenharmony_ci * unaltered. 1858c2ecf20Sopenharmony_ci */ 1868c2ecf20Sopenharmony_ciint ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci return ulist_add_merge(ulist, val, aux, NULL, gfp_mask); 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ciint ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, 1928c2ecf20Sopenharmony_ci u64 *old_aux, gfp_t gfp_mask) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci int ret; 1958c2ecf20Sopenharmony_ci struct ulist_node *node; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci node = ulist_rbtree_search(ulist, val); 1988c2ecf20Sopenharmony_ci if (node) { 1998c2ecf20Sopenharmony_ci if (old_aux) 2008c2ecf20Sopenharmony_ci *old_aux = node->aux; 2018c2ecf20Sopenharmony_ci return 0; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci node = kmalloc(sizeof(*node), gfp_mask); 2048c2ecf20Sopenharmony_ci if (!node) 2058c2ecf20Sopenharmony_ci return -ENOMEM; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci node->val = val; 2088c2ecf20Sopenharmony_ci node->aux = aux; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci ret = ulist_rbtree_insert(ulist, node); 2118c2ecf20Sopenharmony_ci ASSERT(!ret); 2128c2ecf20Sopenharmony_ci list_add_tail(&node->list, &ulist->nodes); 2138c2ecf20Sopenharmony_ci ulist->nnodes++; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci return 1; 2168c2ecf20Sopenharmony_ci} 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci/* 2198c2ecf20Sopenharmony_ci * ulist_del - delete one node from ulist 2208c2ecf20Sopenharmony_ci * @ulist: ulist to remove node from 2218c2ecf20Sopenharmony_ci * @val: value to delete 2228c2ecf20Sopenharmony_ci * @aux: aux to delete 2238c2ecf20Sopenharmony_ci * 2248c2ecf20Sopenharmony_ci * The deletion will only be done when *BOTH* val and aux matches. 2258c2ecf20Sopenharmony_ci * Return 0 for successful delete. 2268c2ecf20Sopenharmony_ci * Return > 0 for not found. 2278c2ecf20Sopenharmony_ci */ 2288c2ecf20Sopenharmony_ciint ulist_del(struct ulist *ulist, u64 val, u64 aux) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci struct ulist_node *node; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci node = ulist_rbtree_search(ulist, val); 2338c2ecf20Sopenharmony_ci /* Not found */ 2348c2ecf20Sopenharmony_ci if (!node) 2358c2ecf20Sopenharmony_ci return 1; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci if (node->aux != aux) 2388c2ecf20Sopenharmony_ci return 1; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* Found and delete */ 2418c2ecf20Sopenharmony_ci ulist_rbtree_erase(ulist, node); 2428c2ecf20Sopenharmony_ci return 0; 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci/** 2468c2ecf20Sopenharmony_ci * ulist_next - iterate ulist 2478c2ecf20Sopenharmony_ci * @ulist: ulist to iterate 2488c2ecf20Sopenharmony_ci * @uiter: iterator variable, initialized with ULIST_ITER_INIT(&iterator) 2498c2ecf20Sopenharmony_ci * 2508c2ecf20Sopenharmony_ci * Note: locking must be provided by the caller. In case of rwlocks only read 2518c2ecf20Sopenharmony_ci * locking is needed 2528c2ecf20Sopenharmony_ci * 2538c2ecf20Sopenharmony_ci * This function is used to iterate an ulist. 2548c2ecf20Sopenharmony_ci * It returns the next element from the ulist or %NULL when the 2558c2ecf20Sopenharmony_ci * end is reached. No guarantee is made with respect to the order in which 2568c2ecf20Sopenharmony_ci * the elements are returned. They might neither be returned in order of 2578c2ecf20Sopenharmony_ci * addition nor in ascending order. 2588c2ecf20Sopenharmony_ci * It is allowed to call ulist_add during an enumeration. Newly added items 2598c2ecf20Sopenharmony_ci * are guaranteed to show up in the running enumeration. 2608c2ecf20Sopenharmony_ci */ 2618c2ecf20Sopenharmony_cistruct ulist_node *ulist_next(struct ulist *ulist, struct ulist_iterator *uiter) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci struct ulist_node *node; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci if (list_empty(&ulist->nodes)) 2668c2ecf20Sopenharmony_ci return NULL; 2678c2ecf20Sopenharmony_ci if (uiter->cur_list && uiter->cur_list->next == &ulist->nodes) 2688c2ecf20Sopenharmony_ci return NULL; 2698c2ecf20Sopenharmony_ci if (uiter->cur_list) { 2708c2ecf20Sopenharmony_ci uiter->cur_list = uiter->cur_list->next; 2718c2ecf20Sopenharmony_ci } else { 2728c2ecf20Sopenharmony_ci uiter->cur_list = ulist->nodes.next; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci node = list_entry(uiter->cur_list, struct ulist_node, list); 2758c2ecf20Sopenharmony_ci return node; 2768c2ecf20Sopenharmony_ci} 277