162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2011 STRATO AG 462306a36Sopenharmony_ci * written by Arne Jansen <sensille@gmx.net> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/slab.h> 862306a36Sopenharmony_ci#include "messages.h" 962306a36Sopenharmony_ci#include "ulist.h" 1062306a36Sopenharmony_ci#include "ctree.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* 1362306a36Sopenharmony_ci * ulist is a generic data structure to hold a collection of unique u64 1462306a36Sopenharmony_ci * values. The only operations it supports is adding to the list and 1562306a36Sopenharmony_ci * enumerating it. 1662306a36Sopenharmony_ci * It is possible to store an auxiliary value along with the key. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * A sample usage for ulists is the enumeration of directed graphs without 1962306a36Sopenharmony_ci * visiting a node twice. The pseudo-code could look like this: 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * ulist = ulist_alloc(); 2262306a36Sopenharmony_ci * ulist_add(ulist, root); 2362306a36Sopenharmony_ci * ULIST_ITER_INIT(&uiter); 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * while ((elem = ulist_next(ulist, &uiter)) { 2662306a36Sopenharmony_ci * for (all child nodes n in elem) 2762306a36Sopenharmony_ci * ulist_add(ulist, n); 2862306a36Sopenharmony_ci * do something useful with the node; 2962306a36Sopenharmony_ci * } 3062306a36Sopenharmony_ci * ulist_free(ulist); 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * This assumes the graph nodes are addressable by u64. This stems from the 3362306a36Sopenharmony_ci * usage for tree enumeration in btrfs, where the logical addresses are 3462306a36Sopenharmony_ci * 64 bit. 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * It is also useful for tree enumeration which could be done elegantly 3762306a36Sopenharmony_ci * recursively, but is not possible due to kernel stack limitations. The 3862306a36Sopenharmony_ci * loop would be similar to the above. 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* 4262306a36Sopenharmony_ci * Freshly initialize a ulist. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * @ulist: the ulist to initialize 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * Note: don't use this function to init an already used ulist, use 4762306a36Sopenharmony_ci * ulist_reinit instead. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_civoid ulist_init(struct ulist *ulist) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci INIT_LIST_HEAD(&ulist->nodes); 5262306a36Sopenharmony_ci ulist->root = RB_ROOT; 5362306a36Sopenharmony_ci ulist->nnodes = 0; 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* 5762306a36Sopenharmony_ci * Free up additionally allocated memory for the ulist. 5862306a36Sopenharmony_ci * 5962306a36Sopenharmony_ci * @ulist: the ulist from which to free the additional memory 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * This is useful in cases where the base 'struct ulist' has been statically 6262306a36Sopenharmony_ci * allocated. 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_civoid ulist_release(struct ulist *ulist) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct ulist_node *node; 6762306a36Sopenharmony_ci struct ulist_node *next; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci list_for_each_entry_safe(node, next, &ulist->nodes, list) { 7062306a36Sopenharmony_ci kfree(node); 7162306a36Sopenharmony_ci } 7262306a36Sopenharmony_ci ulist->root = RB_ROOT; 7362306a36Sopenharmony_ci INIT_LIST_HEAD(&ulist->nodes); 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci/* 7762306a36Sopenharmony_ci * Prepare a ulist for reuse. 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * @ulist: ulist to be reused 8062306a36Sopenharmony_ci * 8162306a36Sopenharmony_ci * Free up all additional memory allocated for the list elements and reinit 8262306a36Sopenharmony_ci * the ulist. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_civoid ulist_reinit(struct ulist *ulist) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci ulist_release(ulist); 8762306a36Sopenharmony_ci ulist_init(ulist); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/* 9162306a36Sopenharmony_ci * Dynamically allocate a ulist. 9262306a36Sopenharmony_ci * 9362306a36Sopenharmony_ci * @gfp_mask: allocation flags to for base allocation 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * The allocated ulist will be returned in an initialized state. 9662306a36Sopenharmony_ci */ 9762306a36Sopenharmony_cistruct ulist *ulist_alloc(gfp_t gfp_mask) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci struct ulist *ulist = kmalloc(sizeof(*ulist), gfp_mask); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (!ulist) 10262306a36Sopenharmony_ci return NULL; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci ulist_init(ulist); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return ulist; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/* 11062306a36Sopenharmony_ci * Free dynamically allocated ulist. 11162306a36Sopenharmony_ci * 11262306a36Sopenharmony_ci * @ulist: ulist to free 11362306a36Sopenharmony_ci * 11462306a36Sopenharmony_ci * It is not necessary to call ulist_release before. 11562306a36Sopenharmony_ci */ 11662306a36Sopenharmony_civoid ulist_free(struct ulist *ulist) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci if (!ulist) 11962306a36Sopenharmony_ci return; 12062306a36Sopenharmony_ci ulist_release(ulist); 12162306a36Sopenharmony_ci kfree(ulist); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic struct ulist_node *ulist_rbtree_search(struct ulist *ulist, u64 val) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct rb_node *n = ulist->root.rb_node; 12762306a36Sopenharmony_ci struct ulist_node *u = NULL; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci while (n) { 13062306a36Sopenharmony_ci u = rb_entry(n, struct ulist_node, rb_node); 13162306a36Sopenharmony_ci if (u->val < val) 13262306a36Sopenharmony_ci n = n->rb_right; 13362306a36Sopenharmony_ci else if (u->val > val) 13462306a36Sopenharmony_ci n = n->rb_left; 13562306a36Sopenharmony_ci else 13662306a36Sopenharmony_ci return u; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci return NULL; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic void ulist_rbtree_erase(struct ulist *ulist, struct ulist_node *node) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci rb_erase(&node->rb_node, &ulist->root); 14462306a36Sopenharmony_ci list_del(&node->list); 14562306a36Sopenharmony_ci kfree(node); 14662306a36Sopenharmony_ci BUG_ON(ulist->nnodes == 0); 14762306a36Sopenharmony_ci ulist->nnodes--; 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic int ulist_rbtree_insert(struct ulist *ulist, struct ulist_node *ins) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci struct rb_node **p = &ulist->root.rb_node; 15362306a36Sopenharmony_ci struct rb_node *parent = NULL; 15462306a36Sopenharmony_ci struct ulist_node *cur = NULL; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci while (*p) { 15762306a36Sopenharmony_ci parent = *p; 15862306a36Sopenharmony_ci cur = rb_entry(parent, struct ulist_node, rb_node); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci if (cur->val < ins->val) 16162306a36Sopenharmony_ci p = &(*p)->rb_right; 16262306a36Sopenharmony_ci else if (cur->val > ins->val) 16362306a36Sopenharmony_ci p = &(*p)->rb_left; 16462306a36Sopenharmony_ci else 16562306a36Sopenharmony_ci return -EEXIST; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci rb_link_node(&ins->rb_node, parent, p); 16862306a36Sopenharmony_ci rb_insert_color(&ins->rb_node, &ulist->root); 16962306a36Sopenharmony_ci return 0; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/* 17362306a36Sopenharmony_ci * Add an element to the ulist. 17462306a36Sopenharmony_ci * 17562306a36Sopenharmony_ci * @ulist: ulist to add the element to 17662306a36Sopenharmony_ci * @val: value to add to ulist 17762306a36Sopenharmony_ci * @aux: auxiliary value to store along with val 17862306a36Sopenharmony_ci * @gfp_mask: flags to use for allocation 17962306a36Sopenharmony_ci * 18062306a36Sopenharmony_ci * Note: locking must be provided by the caller. In case of rwlocks write 18162306a36Sopenharmony_ci * locking is needed 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * Add an element to a ulist. The @val will only be added if it doesn't 18462306a36Sopenharmony_ci * already exist. If it is added, the auxiliary value @aux is stored along with 18562306a36Sopenharmony_ci * it. In case @val already exists in the ulist, @aux is ignored, even if 18662306a36Sopenharmony_ci * it differs from the already stored value. 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * ulist_add returns 0 if @val already exists in ulist and 1 if @val has been 18962306a36Sopenharmony_ci * inserted. 19062306a36Sopenharmony_ci * In case of allocation failure -ENOMEM is returned and the ulist stays 19162306a36Sopenharmony_ci * unaltered. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ciint ulist_add(struct ulist *ulist, u64 val, u64 aux, gfp_t gfp_mask) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci return ulist_add_merge(ulist, val, aux, NULL, gfp_mask); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ciint ulist_add_merge(struct ulist *ulist, u64 val, u64 aux, 19962306a36Sopenharmony_ci u64 *old_aux, gfp_t gfp_mask) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci int ret; 20262306a36Sopenharmony_ci struct ulist_node *node; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci node = ulist_rbtree_search(ulist, val); 20562306a36Sopenharmony_ci if (node) { 20662306a36Sopenharmony_ci if (old_aux) 20762306a36Sopenharmony_ci *old_aux = node->aux; 20862306a36Sopenharmony_ci return 0; 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci node = kmalloc(sizeof(*node), gfp_mask); 21162306a36Sopenharmony_ci if (!node) 21262306a36Sopenharmony_ci return -ENOMEM; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci node->val = val; 21562306a36Sopenharmony_ci node->aux = aux; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci ret = ulist_rbtree_insert(ulist, node); 21862306a36Sopenharmony_ci ASSERT(!ret); 21962306a36Sopenharmony_ci list_add_tail(&node->list, &ulist->nodes); 22062306a36Sopenharmony_ci ulist->nnodes++; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci return 1; 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci/* 22662306a36Sopenharmony_ci * ulist_del - delete one node from ulist 22762306a36Sopenharmony_ci * @ulist: ulist to remove node from 22862306a36Sopenharmony_ci * @val: value to delete 22962306a36Sopenharmony_ci * @aux: aux to delete 23062306a36Sopenharmony_ci * 23162306a36Sopenharmony_ci * The deletion will only be done when *BOTH* val and aux matches. 23262306a36Sopenharmony_ci * Return 0 for successful delete. 23362306a36Sopenharmony_ci * Return > 0 for not found. 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ciint ulist_del(struct ulist *ulist, u64 val, u64 aux) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci struct ulist_node *node; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci node = ulist_rbtree_search(ulist, val); 24062306a36Sopenharmony_ci /* Not found */ 24162306a36Sopenharmony_ci if (!node) 24262306a36Sopenharmony_ci return 1; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (node->aux != aux) 24562306a36Sopenharmony_ci return 1; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* Found and delete */ 24862306a36Sopenharmony_ci ulist_rbtree_erase(ulist, node); 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci/* 25362306a36Sopenharmony_ci * Iterate ulist. 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * @ulist: ulist to iterate 25662306a36Sopenharmony_ci * @uiter: iterator variable, initialized with ULIST_ITER_INIT(&iterator) 25762306a36Sopenharmony_ci * 25862306a36Sopenharmony_ci * Note: locking must be provided by the caller. In case of rwlocks only read 25962306a36Sopenharmony_ci * locking is needed 26062306a36Sopenharmony_ci * 26162306a36Sopenharmony_ci * This function is used to iterate an ulist. 26262306a36Sopenharmony_ci * It returns the next element from the ulist or %NULL when the 26362306a36Sopenharmony_ci * end is reached. No guarantee is made with respect to the order in which 26462306a36Sopenharmony_ci * the elements are returned. They might neither be returned in order of 26562306a36Sopenharmony_ci * addition nor in ascending order. 26662306a36Sopenharmony_ci * It is allowed to call ulist_add during an enumeration. Newly added items 26762306a36Sopenharmony_ci * are guaranteed to show up in the running enumeration. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_cistruct ulist_node *ulist_next(const struct ulist *ulist, struct ulist_iterator *uiter) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci struct ulist_node *node; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if (list_empty(&ulist->nodes)) 27462306a36Sopenharmony_ci return NULL; 27562306a36Sopenharmony_ci if (uiter->cur_list && uiter->cur_list->next == &ulist->nodes) 27662306a36Sopenharmony_ci return NULL; 27762306a36Sopenharmony_ci if (uiter->cur_list) { 27862306a36Sopenharmony_ci uiter->cur_list = uiter->cur_list->next; 27962306a36Sopenharmony_ci } else { 28062306a36Sopenharmony_ci uiter->cur_list = ulist->nodes.next; 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci node = list_entry(uiter->cur_list, struct ulist_node, list); 28362306a36Sopenharmony_ci return node; 28462306a36Sopenharmony_ci} 285