18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2001 Momchil Velikov 48c2ecf20Sopenharmony_ci * Portions Copyright (C) 2001 Christoph Hellwig 58c2ecf20Sopenharmony_ci * Copyright (C) 2005 SGI, Christoph Lameter 68c2ecf20Sopenharmony_ci * Copyright (C) 2006 Nick Piggin 78c2ecf20Sopenharmony_ci * Copyright (C) 2012 Konstantin Khlebnikov 88c2ecf20Sopenharmony_ci * Copyright (C) 2016 Intel, Matthew Wilcox 98c2ecf20Sopenharmony_ci * Copyright (C) 2016 Intel, Ross Zwisler 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 138c2ecf20Sopenharmony_ci#include <linux/bitops.h> 148c2ecf20Sopenharmony_ci#include <linux/bug.h> 158c2ecf20Sopenharmony_ci#include <linux/cpu.h> 168c2ecf20Sopenharmony_ci#include <linux/errno.h> 178c2ecf20Sopenharmony_ci#include <linux/export.h> 188c2ecf20Sopenharmony_ci#include <linux/idr.h> 198c2ecf20Sopenharmony_ci#include <linux/init.h> 208c2ecf20Sopenharmony_ci#include <linux/kernel.h> 218c2ecf20Sopenharmony_ci#include <linux/kmemleak.h> 228c2ecf20Sopenharmony_ci#include <linux/percpu.h> 238c2ecf20Sopenharmony_ci#include <linux/preempt.h> /* in_interrupt() */ 248c2ecf20Sopenharmony_ci#include <linux/radix-tree.h> 258c2ecf20Sopenharmony_ci#include <linux/rcupdate.h> 268c2ecf20Sopenharmony_ci#include <linux/slab.h> 278c2ecf20Sopenharmony_ci#include <linux/string.h> 288c2ecf20Sopenharmony_ci#include <linux/xarray.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* 318c2ecf20Sopenharmony_ci * Radix tree node cache. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_cistruct kmem_cache *radix_tree_node_cachep; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* 368c2ecf20Sopenharmony_ci * The radix tree is variable-height, so an insert operation not only has 378c2ecf20Sopenharmony_ci * to build the branch to its corresponding item, it also has to build the 388c2ecf20Sopenharmony_ci * branch to existing items if the size has to be increased (by 398c2ecf20Sopenharmony_ci * radix_tree_extend). 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * The worst case is a zero height tree with just a single item at index 0, 428c2ecf20Sopenharmony_ci * and then inserting an item at index ULONG_MAX. This requires 2 new branches 438c2ecf20Sopenharmony_ci * of RADIX_TREE_MAX_PATH size to be created, with only the root node shared. 448c2ecf20Sopenharmony_ci * Hence: 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci#define RADIX_TREE_PRELOAD_SIZE (RADIX_TREE_MAX_PATH * 2 - 1) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* 498c2ecf20Sopenharmony_ci * The IDR does not have to be as high as the radix tree since it uses 508c2ecf20Sopenharmony_ci * signed integers, not unsigned longs. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci#define IDR_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(int) - 1) 538c2ecf20Sopenharmony_ci#define IDR_MAX_PATH (DIV_ROUND_UP(IDR_INDEX_BITS, \ 548c2ecf20Sopenharmony_ci RADIX_TREE_MAP_SHIFT)) 558c2ecf20Sopenharmony_ci#define IDR_PRELOAD_SIZE (IDR_MAX_PATH * 2 - 1) 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* 588c2ecf20Sopenharmony_ci * Per-cpu pool of preloaded nodes 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ciDEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 618c2ecf20Sopenharmony_ci .lock = INIT_LOCAL_LOCK(lock), 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ciEXPORT_PER_CPU_SYMBOL_GPL(radix_tree_preloads); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic inline struct radix_tree_node *entry_to_node(void *ptr) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci return (void *)((unsigned long)ptr & ~RADIX_TREE_INTERNAL_NODE); 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic inline void *node_to_entry(void *ptr) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci return (void *)((unsigned long)ptr | RADIX_TREE_INTERNAL_NODE); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define RADIX_TREE_RETRY XA_RETRY_ENTRY 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic inline unsigned long 788c2ecf20Sopenharmony_ciget_slot_offset(const struct radix_tree_node *parent, void __rcu **slot) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci return parent ? slot - parent->slots : 0; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic unsigned int radix_tree_descend(const struct radix_tree_node *parent, 848c2ecf20Sopenharmony_ci struct radix_tree_node **nodep, unsigned long index) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci unsigned int offset = (index >> parent->shift) & RADIX_TREE_MAP_MASK; 878c2ecf20Sopenharmony_ci void __rcu **entry = rcu_dereference_raw(parent->slots[offset]); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci *nodep = (void *)entry; 908c2ecf20Sopenharmony_ci return offset; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic inline gfp_t root_gfp_mask(const struct radix_tree_root *root) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci return root->xa_flags & (__GFP_BITS_MASK & ~GFP_ZONEMASK); 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic inline void tag_set(struct radix_tree_node *node, unsigned int tag, 998c2ecf20Sopenharmony_ci int offset) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci __set_bit(offset, node->tags[tag]); 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic inline void tag_clear(struct radix_tree_node *node, unsigned int tag, 1058c2ecf20Sopenharmony_ci int offset) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci __clear_bit(offset, node->tags[tag]); 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic inline int tag_get(const struct radix_tree_node *node, unsigned int tag, 1118c2ecf20Sopenharmony_ci int offset) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci return test_bit(offset, node->tags[tag]); 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic inline void root_tag_set(struct radix_tree_root *root, unsigned tag) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci root->xa_flags |= (__force gfp_t)(1 << (tag + ROOT_TAG_SHIFT)); 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic inline void root_tag_clear(struct radix_tree_root *root, unsigned tag) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci root->xa_flags &= (__force gfp_t)~(1 << (tag + ROOT_TAG_SHIFT)); 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic inline void root_tag_clear_all(struct radix_tree_root *root) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci root->xa_flags &= (__force gfp_t)((1 << ROOT_TAG_SHIFT) - 1); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic inline int root_tag_get(const struct radix_tree_root *root, unsigned tag) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci return (__force int)root->xa_flags & (1 << (tag + ROOT_TAG_SHIFT)); 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic inline unsigned root_tags_get(const struct radix_tree_root *root) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci return (__force unsigned)root->xa_flags >> ROOT_TAG_SHIFT; 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic inline bool is_idr(const struct radix_tree_root *root) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci return !!(root->xa_flags & ROOT_IS_IDR); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci/* 1478c2ecf20Sopenharmony_ci * Returns 1 if any slot in the node has this tag set. 1488c2ecf20Sopenharmony_ci * Otherwise returns 0. 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_cistatic inline int any_tag_set(const struct radix_tree_node *node, 1518c2ecf20Sopenharmony_ci unsigned int tag) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci unsigned idx; 1548c2ecf20Sopenharmony_ci for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) { 1558c2ecf20Sopenharmony_ci if (node->tags[tag][idx]) 1568c2ecf20Sopenharmony_ci return 1; 1578c2ecf20Sopenharmony_ci } 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic inline void all_tag_set(struct radix_tree_node *node, unsigned int tag) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci bitmap_fill(node->tags[tag], RADIX_TREE_MAP_SIZE); 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/** 1678c2ecf20Sopenharmony_ci * radix_tree_find_next_bit - find the next set bit in a memory region 1688c2ecf20Sopenharmony_ci * 1698c2ecf20Sopenharmony_ci * @addr: The address to base the search on 1708c2ecf20Sopenharmony_ci * @size: The bitmap size in bits 1718c2ecf20Sopenharmony_ci * @offset: The bitnumber to start searching at 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * Unrollable variant of find_next_bit() for constant size arrays. 1748c2ecf20Sopenharmony_ci * Tail bits starting from size to roundup(size, BITS_PER_LONG) must be zero. 1758c2ecf20Sopenharmony_ci * Returns next bit offset, or size if nothing found. 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_cistatic __always_inline unsigned long 1788c2ecf20Sopenharmony_ciradix_tree_find_next_bit(struct radix_tree_node *node, unsigned int tag, 1798c2ecf20Sopenharmony_ci unsigned long offset) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci const unsigned long *addr = node->tags[tag]; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (offset < RADIX_TREE_MAP_SIZE) { 1848c2ecf20Sopenharmony_ci unsigned long tmp; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci addr += offset / BITS_PER_LONG; 1878c2ecf20Sopenharmony_ci tmp = *addr >> (offset % BITS_PER_LONG); 1888c2ecf20Sopenharmony_ci if (tmp) 1898c2ecf20Sopenharmony_ci return __ffs(tmp) + offset; 1908c2ecf20Sopenharmony_ci offset = (offset + BITS_PER_LONG) & ~(BITS_PER_LONG - 1); 1918c2ecf20Sopenharmony_ci while (offset < RADIX_TREE_MAP_SIZE) { 1928c2ecf20Sopenharmony_ci tmp = *++addr; 1938c2ecf20Sopenharmony_ci if (tmp) 1948c2ecf20Sopenharmony_ci return __ffs(tmp) + offset; 1958c2ecf20Sopenharmony_ci offset += BITS_PER_LONG; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci return RADIX_TREE_MAP_SIZE; 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic unsigned int iter_offset(const struct radix_tree_iter *iter) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci return iter->index & RADIX_TREE_MAP_MASK; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci/* 2078c2ecf20Sopenharmony_ci * The maximum index which can be stored in a radix tree 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_cistatic inline unsigned long shift_maxindex(unsigned int shift) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci return (RADIX_TREE_MAP_SIZE << shift) - 1; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic inline unsigned long node_maxindex(const struct radix_tree_node *node) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci return shift_maxindex(node->shift); 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic unsigned long next_index(unsigned long index, 2208c2ecf20Sopenharmony_ci const struct radix_tree_node *node, 2218c2ecf20Sopenharmony_ci unsigned long offset) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci return (index & ~node_maxindex(node)) + (offset << node->shift); 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci/* 2278c2ecf20Sopenharmony_ci * This assumes that the caller has performed appropriate preallocation, and 2288c2ecf20Sopenharmony_ci * that the caller has pinned this thread of control to the current CPU. 2298c2ecf20Sopenharmony_ci */ 2308c2ecf20Sopenharmony_cistatic struct radix_tree_node * 2318c2ecf20Sopenharmony_ciradix_tree_node_alloc(gfp_t gfp_mask, struct radix_tree_node *parent, 2328c2ecf20Sopenharmony_ci struct radix_tree_root *root, 2338c2ecf20Sopenharmony_ci unsigned int shift, unsigned int offset, 2348c2ecf20Sopenharmony_ci unsigned int count, unsigned int nr_values) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci struct radix_tree_node *ret = NULL; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci /* 2398c2ecf20Sopenharmony_ci * Preload code isn't irq safe and it doesn't make sense to use 2408c2ecf20Sopenharmony_ci * preloading during an interrupt anyway as all the allocations have 2418c2ecf20Sopenharmony_ci * to be atomic. So just do normal allocation when in interrupt. 2428c2ecf20Sopenharmony_ci */ 2438c2ecf20Sopenharmony_ci if (!gfpflags_allow_blocking(gfp_mask) && !in_interrupt()) { 2448c2ecf20Sopenharmony_ci struct radix_tree_preload *rtp; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* 2478c2ecf20Sopenharmony_ci * Even if the caller has preloaded, try to allocate from the 2488c2ecf20Sopenharmony_ci * cache first for the new node to get accounted to the memory 2498c2ecf20Sopenharmony_ci * cgroup. 2508c2ecf20Sopenharmony_ci */ 2518c2ecf20Sopenharmony_ci ret = kmem_cache_alloc(radix_tree_node_cachep, 2528c2ecf20Sopenharmony_ci gfp_mask | __GFP_NOWARN); 2538c2ecf20Sopenharmony_ci if (ret) 2548c2ecf20Sopenharmony_ci goto out; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* 2578c2ecf20Sopenharmony_ci * Provided the caller has preloaded here, we will always 2588c2ecf20Sopenharmony_ci * succeed in getting a node here (and never reach 2598c2ecf20Sopenharmony_ci * kmem_cache_alloc) 2608c2ecf20Sopenharmony_ci */ 2618c2ecf20Sopenharmony_ci rtp = this_cpu_ptr(&radix_tree_preloads); 2628c2ecf20Sopenharmony_ci if (rtp->nr) { 2638c2ecf20Sopenharmony_ci ret = rtp->nodes; 2648c2ecf20Sopenharmony_ci rtp->nodes = ret->parent; 2658c2ecf20Sopenharmony_ci rtp->nr--; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci /* 2688c2ecf20Sopenharmony_ci * Update the allocation stack trace as this is more useful 2698c2ecf20Sopenharmony_ci * for debugging. 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_ci kmemleak_update_trace(ret); 2728c2ecf20Sopenharmony_ci goto out; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci ret = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask); 2758c2ecf20Sopenharmony_ciout: 2768c2ecf20Sopenharmony_ci BUG_ON(radix_tree_is_internal_node(ret)); 2778c2ecf20Sopenharmony_ci if (ret) { 2788c2ecf20Sopenharmony_ci ret->shift = shift; 2798c2ecf20Sopenharmony_ci ret->offset = offset; 2808c2ecf20Sopenharmony_ci ret->count = count; 2818c2ecf20Sopenharmony_ci ret->nr_values = nr_values; 2828c2ecf20Sopenharmony_ci ret->parent = parent; 2838c2ecf20Sopenharmony_ci ret->array = root; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci return ret; 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_civoid radix_tree_node_rcu_free(struct rcu_head *head) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci struct radix_tree_node *node = 2918c2ecf20Sopenharmony_ci container_of(head, struct radix_tree_node, rcu_head); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* 2948c2ecf20Sopenharmony_ci * Must only free zeroed nodes into the slab. We can be left with 2958c2ecf20Sopenharmony_ci * non-NULL entries by radix_tree_free_nodes, so clear the entries 2968c2ecf20Sopenharmony_ci * and tags here. 2978c2ecf20Sopenharmony_ci */ 2988c2ecf20Sopenharmony_ci memset(node->slots, 0, sizeof(node->slots)); 2998c2ecf20Sopenharmony_ci memset(node->tags, 0, sizeof(node->tags)); 3008c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&node->private_list); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci kmem_cache_free(radix_tree_node_cachep, node); 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic inline void 3068c2ecf20Sopenharmony_ciradix_tree_node_free(struct radix_tree_node *node) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci call_rcu(&node->rcu_head, radix_tree_node_rcu_free); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci/* 3128c2ecf20Sopenharmony_ci * Load up this CPU's radix_tree_node buffer with sufficient objects to 3138c2ecf20Sopenharmony_ci * ensure that the addition of a single element in the tree cannot fail. On 3148c2ecf20Sopenharmony_ci * success, return zero, with preemption disabled. On error, return -ENOMEM 3158c2ecf20Sopenharmony_ci * with preemption not disabled. 3168c2ecf20Sopenharmony_ci * 3178c2ecf20Sopenharmony_ci * To make use of this facility, the radix tree must be initialised without 3188c2ecf20Sopenharmony_ci * __GFP_DIRECT_RECLAIM being passed to INIT_RADIX_TREE(). 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_cistatic __must_check int __radix_tree_preload(gfp_t gfp_mask, unsigned nr) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci struct radix_tree_preload *rtp; 3238c2ecf20Sopenharmony_ci struct radix_tree_node *node; 3248c2ecf20Sopenharmony_ci int ret = -ENOMEM; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* 3278c2ecf20Sopenharmony_ci * Nodes preloaded by one cgroup can be used by another cgroup, so 3288c2ecf20Sopenharmony_ci * they should never be accounted to any particular memory cgroup. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_ci gfp_mask &= ~__GFP_ACCOUNT; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci local_lock(&radix_tree_preloads.lock); 3338c2ecf20Sopenharmony_ci rtp = this_cpu_ptr(&radix_tree_preloads); 3348c2ecf20Sopenharmony_ci while (rtp->nr < nr) { 3358c2ecf20Sopenharmony_ci local_unlock(&radix_tree_preloads.lock); 3368c2ecf20Sopenharmony_ci node = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask); 3378c2ecf20Sopenharmony_ci if (node == NULL) 3388c2ecf20Sopenharmony_ci goto out; 3398c2ecf20Sopenharmony_ci local_lock(&radix_tree_preloads.lock); 3408c2ecf20Sopenharmony_ci rtp = this_cpu_ptr(&radix_tree_preloads); 3418c2ecf20Sopenharmony_ci if (rtp->nr < nr) { 3428c2ecf20Sopenharmony_ci node->parent = rtp->nodes; 3438c2ecf20Sopenharmony_ci rtp->nodes = node; 3448c2ecf20Sopenharmony_ci rtp->nr++; 3458c2ecf20Sopenharmony_ci } else { 3468c2ecf20Sopenharmony_ci kmem_cache_free(radix_tree_node_cachep, node); 3478c2ecf20Sopenharmony_ci } 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci ret = 0; 3508c2ecf20Sopenharmony_ciout: 3518c2ecf20Sopenharmony_ci return ret; 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci/* 3558c2ecf20Sopenharmony_ci * Load up this CPU's radix_tree_node buffer with sufficient objects to 3568c2ecf20Sopenharmony_ci * ensure that the addition of a single element in the tree cannot fail. On 3578c2ecf20Sopenharmony_ci * success, return zero, with preemption disabled. On error, return -ENOMEM 3588c2ecf20Sopenharmony_ci * with preemption not disabled. 3598c2ecf20Sopenharmony_ci * 3608c2ecf20Sopenharmony_ci * To make use of this facility, the radix tree must be initialised without 3618c2ecf20Sopenharmony_ci * __GFP_DIRECT_RECLAIM being passed to INIT_RADIX_TREE(). 3628c2ecf20Sopenharmony_ci */ 3638c2ecf20Sopenharmony_ciint radix_tree_preload(gfp_t gfp_mask) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci /* Warn on non-sensical use... */ 3668c2ecf20Sopenharmony_ci WARN_ON_ONCE(!gfpflags_allow_blocking(gfp_mask)); 3678c2ecf20Sopenharmony_ci return __radix_tree_preload(gfp_mask, RADIX_TREE_PRELOAD_SIZE); 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_preload); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci/* 3728c2ecf20Sopenharmony_ci * The same as above function, except we don't guarantee preloading happens. 3738c2ecf20Sopenharmony_ci * We do it, if we decide it helps. On success, return zero with preemption 3748c2ecf20Sopenharmony_ci * disabled. On error, return -ENOMEM with preemption not disabled. 3758c2ecf20Sopenharmony_ci */ 3768c2ecf20Sopenharmony_ciint radix_tree_maybe_preload(gfp_t gfp_mask) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci if (gfpflags_allow_blocking(gfp_mask)) 3798c2ecf20Sopenharmony_ci return __radix_tree_preload(gfp_mask, RADIX_TREE_PRELOAD_SIZE); 3808c2ecf20Sopenharmony_ci /* Preloading doesn't help anything with this gfp mask, skip it */ 3818c2ecf20Sopenharmony_ci local_lock(&radix_tree_preloads.lock); 3828c2ecf20Sopenharmony_ci return 0; 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_maybe_preload); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_cistatic unsigned radix_tree_load_root(const struct radix_tree_root *root, 3878c2ecf20Sopenharmony_ci struct radix_tree_node **nodep, unsigned long *maxindex) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci struct radix_tree_node *node = rcu_dereference_raw(root->xa_head); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci *nodep = node; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci if (likely(radix_tree_is_internal_node(node))) { 3948c2ecf20Sopenharmony_ci node = entry_to_node(node); 3958c2ecf20Sopenharmony_ci *maxindex = node_maxindex(node); 3968c2ecf20Sopenharmony_ci return node->shift + RADIX_TREE_MAP_SHIFT; 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci *maxindex = 0; 4008c2ecf20Sopenharmony_ci return 0; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci/* 4048c2ecf20Sopenharmony_ci * Extend a radix tree so it can store key @index. 4058c2ecf20Sopenharmony_ci */ 4068c2ecf20Sopenharmony_cistatic int radix_tree_extend(struct radix_tree_root *root, gfp_t gfp, 4078c2ecf20Sopenharmony_ci unsigned long index, unsigned int shift) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci void *entry; 4108c2ecf20Sopenharmony_ci unsigned int maxshift; 4118c2ecf20Sopenharmony_ci int tag; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci /* Figure out what the shift should be. */ 4148c2ecf20Sopenharmony_ci maxshift = shift; 4158c2ecf20Sopenharmony_ci while (index > shift_maxindex(maxshift)) 4168c2ecf20Sopenharmony_ci maxshift += RADIX_TREE_MAP_SHIFT; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci entry = rcu_dereference_raw(root->xa_head); 4198c2ecf20Sopenharmony_ci if (!entry && (!is_idr(root) || root_tag_get(root, IDR_FREE))) 4208c2ecf20Sopenharmony_ci goto out; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci do { 4238c2ecf20Sopenharmony_ci struct radix_tree_node *node = radix_tree_node_alloc(gfp, NULL, 4248c2ecf20Sopenharmony_ci root, shift, 0, 1, 0); 4258c2ecf20Sopenharmony_ci if (!node) 4268c2ecf20Sopenharmony_ci return -ENOMEM; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci if (is_idr(root)) { 4298c2ecf20Sopenharmony_ci all_tag_set(node, IDR_FREE); 4308c2ecf20Sopenharmony_ci if (!root_tag_get(root, IDR_FREE)) { 4318c2ecf20Sopenharmony_ci tag_clear(node, IDR_FREE, 0); 4328c2ecf20Sopenharmony_ci root_tag_set(root, IDR_FREE); 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci } else { 4358c2ecf20Sopenharmony_ci /* Propagate the aggregated tag info to the new child */ 4368c2ecf20Sopenharmony_ci for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { 4378c2ecf20Sopenharmony_ci if (root_tag_get(root, tag)) 4388c2ecf20Sopenharmony_ci tag_set(node, tag, 0); 4398c2ecf20Sopenharmony_ci } 4408c2ecf20Sopenharmony_ci } 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci BUG_ON(shift > BITS_PER_LONG); 4438c2ecf20Sopenharmony_ci if (radix_tree_is_internal_node(entry)) { 4448c2ecf20Sopenharmony_ci entry_to_node(entry)->parent = node; 4458c2ecf20Sopenharmony_ci } else if (xa_is_value(entry)) { 4468c2ecf20Sopenharmony_ci /* Moving a value entry root->xa_head to a node */ 4478c2ecf20Sopenharmony_ci node->nr_values = 1; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci /* 4508c2ecf20Sopenharmony_ci * entry was already in the radix tree, so we do not need 4518c2ecf20Sopenharmony_ci * rcu_assign_pointer here 4528c2ecf20Sopenharmony_ci */ 4538c2ecf20Sopenharmony_ci node->slots[0] = (void __rcu *)entry; 4548c2ecf20Sopenharmony_ci entry = node_to_entry(node); 4558c2ecf20Sopenharmony_ci rcu_assign_pointer(root->xa_head, entry); 4568c2ecf20Sopenharmony_ci shift += RADIX_TREE_MAP_SHIFT; 4578c2ecf20Sopenharmony_ci } while (shift <= maxshift); 4588c2ecf20Sopenharmony_ciout: 4598c2ecf20Sopenharmony_ci return maxshift + RADIX_TREE_MAP_SHIFT; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci/** 4638c2ecf20Sopenharmony_ci * radix_tree_shrink - shrink radix tree to minimum height 4648c2ecf20Sopenharmony_ci * @root radix tree root 4658c2ecf20Sopenharmony_ci */ 4668c2ecf20Sopenharmony_cistatic inline bool radix_tree_shrink(struct radix_tree_root *root) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci bool shrunk = false; 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci for (;;) { 4718c2ecf20Sopenharmony_ci struct radix_tree_node *node = rcu_dereference_raw(root->xa_head); 4728c2ecf20Sopenharmony_ci struct radix_tree_node *child; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci if (!radix_tree_is_internal_node(node)) 4758c2ecf20Sopenharmony_ci break; 4768c2ecf20Sopenharmony_ci node = entry_to_node(node); 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci /* 4798c2ecf20Sopenharmony_ci * The candidate node has more than one child, or its child 4808c2ecf20Sopenharmony_ci * is not at the leftmost slot, we cannot shrink. 4818c2ecf20Sopenharmony_ci */ 4828c2ecf20Sopenharmony_ci if (node->count != 1) 4838c2ecf20Sopenharmony_ci break; 4848c2ecf20Sopenharmony_ci child = rcu_dereference_raw(node->slots[0]); 4858c2ecf20Sopenharmony_ci if (!child) 4868c2ecf20Sopenharmony_ci break; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci /* 4898c2ecf20Sopenharmony_ci * For an IDR, we must not shrink entry 0 into the root in 4908c2ecf20Sopenharmony_ci * case somebody calls idr_replace() with a pointer that 4918c2ecf20Sopenharmony_ci * appears to be an internal entry 4928c2ecf20Sopenharmony_ci */ 4938c2ecf20Sopenharmony_ci if (!node->shift && is_idr(root)) 4948c2ecf20Sopenharmony_ci break; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if (radix_tree_is_internal_node(child)) 4978c2ecf20Sopenharmony_ci entry_to_node(child)->parent = NULL; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci /* 5008c2ecf20Sopenharmony_ci * We don't need rcu_assign_pointer(), since we are simply 5018c2ecf20Sopenharmony_ci * moving the node from one part of the tree to another: if it 5028c2ecf20Sopenharmony_ci * was safe to dereference the old pointer to it 5038c2ecf20Sopenharmony_ci * (node->slots[0]), it will be safe to dereference the new 5048c2ecf20Sopenharmony_ci * one (root->xa_head) as far as dependent read barriers go. 5058c2ecf20Sopenharmony_ci */ 5068c2ecf20Sopenharmony_ci root->xa_head = (void __rcu *)child; 5078c2ecf20Sopenharmony_ci if (is_idr(root) && !tag_get(node, IDR_FREE, 0)) 5088c2ecf20Sopenharmony_ci root_tag_clear(root, IDR_FREE); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci /* 5118c2ecf20Sopenharmony_ci * We have a dilemma here. The node's slot[0] must not be 5128c2ecf20Sopenharmony_ci * NULLed in case there are concurrent lookups expecting to 5138c2ecf20Sopenharmony_ci * find the item. However if this was a bottom-level node, 5148c2ecf20Sopenharmony_ci * then it may be subject to the slot pointer being visible 5158c2ecf20Sopenharmony_ci * to callers dereferencing it. If item corresponding to 5168c2ecf20Sopenharmony_ci * slot[0] is subsequently deleted, these callers would expect 5178c2ecf20Sopenharmony_ci * their slot to become empty sooner or later. 5188c2ecf20Sopenharmony_ci * 5198c2ecf20Sopenharmony_ci * For example, lockless pagecache will look up a slot, deref 5208c2ecf20Sopenharmony_ci * the page pointer, and if the page has 0 refcount it means it 5218c2ecf20Sopenharmony_ci * was concurrently deleted from pagecache so try the deref 5228c2ecf20Sopenharmony_ci * again. Fortunately there is already a requirement for logic 5238c2ecf20Sopenharmony_ci * to retry the entire slot lookup -- the indirect pointer 5248c2ecf20Sopenharmony_ci * problem (replacing direct root node with an indirect pointer 5258c2ecf20Sopenharmony_ci * also results in a stale slot). So tag the slot as indirect 5268c2ecf20Sopenharmony_ci * to force callers to retry. 5278c2ecf20Sopenharmony_ci */ 5288c2ecf20Sopenharmony_ci node->count = 0; 5298c2ecf20Sopenharmony_ci if (!radix_tree_is_internal_node(child)) { 5308c2ecf20Sopenharmony_ci node->slots[0] = (void __rcu *)RADIX_TREE_RETRY; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci WARN_ON_ONCE(!list_empty(&node->private_list)); 5348c2ecf20Sopenharmony_ci radix_tree_node_free(node); 5358c2ecf20Sopenharmony_ci shrunk = true; 5368c2ecf20Sopenharmony_ci } 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci return shrunk; 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic bool delete_node(struct radix_tree_root *root, 5428c2ecf20Sopenharmony_ci struct radix_tree_node *node) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci bool deleted = false; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci do { 5478c2ecf20Sopenharmony_ci struct radix_tree_node *parent; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci if (node->count) { 5508c2ecf20Sopenharmony_ci if (node_to_entry(node) == 5518c2ecf20Sopenharmony_ci rcu_dereference_raw(root->xa_head)) 5528c2ecf20Sopenharmony_ci deleted |= radix_tree_shrink(root); 5538c2ecf20Sopenharmony_ci return deleted; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci parent = node->parent; 5578c2ecf20Sopenharmony_ci if (parent) { 5588c2ecf20Sopenharmony_ci parent->slots[node->offset] = NULL; 5598c2ecf20Sopenharmony_ci parent->count--; 5608c2ecf20Sopenharmony_ci } else { 5618c2ecf20Sopenharmony_ci /* 5628c2ecf20Sopenharmony_ci * Shouldn't the tags already have all been cleared 5638c2ecf20Sopenharmony_ci * by the caller? 5648c2ecf20Sopenharmony_ci */ 5658c2ecf20Sopenharmony_ci if (!is_idr(root)) 5668c2ecf20Sopenharmony_ci root_tag_clear_all(root); 5678c2ecf20Sopenharmony_ci root->xa_head = NULL; 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci WARN_ON_ONCE(!list_empty(&node->private_list)); 5718c2ecf20Sopenharmony_ci radix_tree_node_free(node); 5728c2ecf20Sopenharmony_ci deleted = true; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci node = parent; 5758c2ecf20Sopenharmony_ci } while (node); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci return deleted; 5788c2ecf20Sopenharmony_ci} 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci/** 5818c2ecf20Sopenharmony_ci * __radix_tree_create - create a slot in a radix tree 5828c2ecf20Sopenharmony_ci * @root: radix tree root 5838c2ecf20Sopenharmony_ci * @index: index key 5848c2ecf20Sopenharmony_ci * @nodep: returns node 5858c2ecf20Sopenharmony_ci * @slotp: returns slot 5868c2ecf20Sopenharmony_ci * 5878c2ecf20Sopenharmony_ci * Create, if necessary, and return the node and slot for an item 5888c2ecf20Sopenharmony_ci * at position @index in the radix tree @root. 5898c2ecf20Sopenharmony_ci * 5908c2ecf20Sopenharmony_ci * Until there is more than one item in the tree, no nodes are 5918c2ecf20Sopenharmony_ci * allocated and @root->xa_head is used as a direct slot instead of 5928c2ecf20Sopenharmony_ci * pointing to a node, in which case *@nodep will be NULL. 5938c2ecf20Sopenharmony_ci * 5948c2ecf20Sopenharmony_ci * Returns -ENOMEM, or 0 for success. 5958c2ecf20Sopenharmony_ci */ 5968c2ecf20Sopenharmony_cistatic int __radix_tree_create(struct radix_tree_root *root, 5978c2ecf20Sopenharmony_ci unsigned long index, struct radix_tree_node **nodep, 5988c2ecf20Sopenharmony_ci void __rcu ***slotp) 5998c2ecf20Sopenharmony_ci{ 6008c2ecf20Sopenharmony_ci struct radix_tree_node *node = NULL, *child; 6018c2ecf20Sopenharmony_ci void __rcu **slot = (void __rcu **)&root->xa_head; 6028c2ecf20Sopenharmony_ci unsigned long maxindex; 6038c2ecf20Sopenharmony_ci unsigned int shift, offset = 0; 6048c2ecf20Sopenharmony_ci unsigned long max = index; 6058c2ecf20Sopenharmony_ci gfp_t gfp = root_gfp_mask(root); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci shift = radix_tree_load_root(root, &child, &maxindex); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci /* Make sure the tree is high enough. */ 6108c2ecf20Sopenharmony_ci if (max > maxindex) { 6118c2ecf20Sopenharmony_ci int error = radix_tree_extend(root, gfp, max, shift); 6128c2ecf20Sopenharmony_ci if (error < 0) 6138c2ecf20Sopenharmony_ci return error; 6148c2ecf20Sopenharmony_ci shift = error; 6158c2ecf20Sopenharmony_ci child = rcu_dereference_raw(root->xa_head); 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci while (shift > 0) { 6198c2ecf20Sopenharmony_ci shift -= RADIX_TREE_MAP_SHIFT; 6208c2ecf20Sopenharmony_ci if (child == NULL) { 6218c2ecf20Sopenharmony_ci /* Have to add a child node. */ 6228c2ecf20Sopenharmony_ci child = radix_tree_node_alloc(gfp, node, root, shift, 6238c2ecf20Sopenharmony_ci offset, 0, 0); 6248c2ecf20Sopenharmony_ci if (!child) 6258c2ecf20Sopenharmony_ci return -ENOMEM; 6268c2ecf20Sopenharmony_ci rcu_assign_pointer(*slot, node_to_entry(child)); 6278c2ecf20Sopenharmony_ci if (node) 6288c2ecf20Sopenharmony_ci node->count++; 6298c2ecf20Sopenharmony_ci } else if (!radix_tree_is_internal_node(child)) 6308c2ecf20Sopenharmony_ci break; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci /* Go a level down */ 6338c2ecf20Sopenharmony_ci node = entry_to_node(child); 6348c2ecf20Sopenharmony_ci offset = radix_tree_descend(node, &child, index); 6358c2ecf20Sopenharmony_ci slot = &node->slots[offset]; 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci if (nodep) 6398c2ecf20Sopenharmony_ci *nodep = node; 6408c2ecf20Sopenharmony_ci if (slotp) 6418c2ecf20Sopenharmony_ci *slotp = slot; 6428c2ecf20Sopenharmony_ci return 0; 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci/* 6468c2ecf20Sopenharmony_ci * Free any nodes below this node. The tree is presumed to not need 6478c2ecf20Sopenharmony_ci * shrinking, and any user data in the tree is presumed to not need a 6488c2ecf20Sopenharmony_ci * destructor called on it. If we need to add a destructor, we can 6498c2ecf20Sopenharmony_ci * add that functionality later. Note that we may not clear tags or 6508c2ecf20Sopenharmony_ci * slots from the tree as an RCU walker may still have a pointer into 6518c2ecf20Sopenharmony_ci * this subtree. We could replace the entries with RADIX_TREE_RETRY, 6528c2ecf20Sopenharmony_ci * but we'll still have to clear those in rcu_free. 6538c2ecf20Sopenharmony_ci */ 6548c2ecf20Sopenharmony_cistatic void radix_tree_free_nodes(struct radix_tree_node *node) 6558c2ecf20Sopenharmony_ci{ 6568c2ecf20Sopenharmony_ci unsigned offset = 0; 6578c2ecf20Sopenharmony_ci struct radix_tree_node *child = entry_to_node(node); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci for (;;) { 6608c2ecf20Sopenharmony_ci void *entry = rcu_dereference_raw(child->slots[offset]); 6618c2ecf20Sopenharmony_ci if (xa_is_node(entry) && child->shift) { 6628c2ecf20Sopenharmony_ci child = entry_to_node(entry); 6638c2ecf20Sopenharmony_ci offset = 0; 6648c2ecf20Sopenharmony_ci continue; 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci offset++; 6678c2ecf20Sopenharmony_ci while (offset == RADIX_TREE_MAP_SIZE) { 6688c2ecf20Sopenharmony_ci struct radix_tree_node *old = child; 6698c2ecf20Sopenharmony_ci offset = child->offset + 1; 6708c2ecf20Sopenharmony_ci child = child->parent; 6718c2ecf20Sopenharmony_ci WARN_ON_ONCE(!list_empty(&old->private_list)); 6728c2ecf20Sopenharmony_ci radix_tree_node_free(old); 6738c2ecf20Sopenharmony_ci if (old == entry_to_node(node)) 6748c2ecf20Sopenharmony_ci return; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci } 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic inline int insert_entries(struct radix_tree_node *node, 6808c2ecf20Sopenharmony_ci void __rcu **slot, void *item, bool replace) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci if (*slot) 6838c2ecf20Sopenharmony_ci return -EEXIST; 6848c2ecf20Sopenharmony_ci rcu_assign_pointer(*slot, item); 6858c2ecf20Sopenharmony_ci if (node) { 6868c2ecf20Sopenharmony_ci node->count++; 6878c2ecf20Sopenharmony_ci if (xa_is_value(item)) 6888c2ecf20Sopenharmony_ci node->nr_values++; 6898c2ecf20Sopenharmony_ci } 6908c2ecf20Sopenharmony_ci return 1; 6918c2ecf20Sopenharmony_ci} 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci/** 6948c2ecf20Sopenharmony_ci * __radix_tree_insert - insert into a radix tree 6958c2ecf20Sopenharmony_ci * @root: radix tree root 6968c2ecf20Sopenharmony_ci * @index: index key 6978c2ecf20Sopenharmony_ci * @item: item to insert 6988c2ecf20Sopenharmony_ci * 6998c2ecf20Sopenharmony_ci * Insert an item into the radix tree at position @index. 7008c2ecf20Sopenharmony_ci */ 7018c2ecf20Sopenharmony_ciint radix_tree_insert(struct radix_tree_root *root, unsigned long index, 7028c2ecf20Sopenharmony_ci void *item) 7038c2ecf20Sopenharmony_ci{ 7048c2ecf20Sopenharmony_ci struct radix_tree_node *node; 7058c2ecf20Sopenharmony_ci void __rcu **slot; 7068c2ecf20Sopenharmony_ci int error; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci BUG_ON(radix_tree_is_internal_node(item)); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci error = __radix_tree_create(root, index, &node, &slot); 7118c2ecf20Sopenharmony_ci if (error) 7128c2ecf20Sopenharmony_ci return error; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci error = insert_entries(node, slot, item, false); 7158c2ecf20Sopenharmony_ci if (error < 0) 7168c2ecf20Sopenharmony_ci return error; 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci if (node) { 7198c2ecf20Sopenharmony_ci unsigned offset = get_slot_offset(node, slot); 7208c2ecf20Sopenharmony_ci BUG_ON(tag_get(node, 0, offset)); 7218c2ecf20Sopenharmony_ci BUG_ON(tag_get(node, 1, offset)); 7228c2ecf20Sopenharmony_ci BUG_ON(tag_get(node, 2, offset)); 7238c2ecf20Sopenharmony_ci } else { 7248c2ecf20Sopenharmony_ci BUG_ON(root_tags_get(root)); 7258c2ecf20Sopenharmony_ci } 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci return 0; 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_insert); 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci/** 7328c2ecf20Sopenharmony_ci * __radix_tree_lookup - lookup an item in a radix tree 7338c2ecf20Sopenharmony_ci * @root: radix tree root 7348c2ecf20Sopenharmony_ci * @index: index key 7358c2ecf20Sopenharmony_ci * @nodep: returns node 7368c2ecf20Sopenharmony_ci * @slotp: returns slot 7378c2ecf20Sopenharmony_ci * 7388c2ecf20Sopenharmony_ci * Lookup and return the item at position @index in the radix 7398c2ecf20Sopenharmony_ci * tree @root. 7408c2ecf20Sopenharmony_ci * 7418c2ecf20Sopenharmony_ci * Until there is more than one item in the tree, no nodes are 7428c2ecf20Sopenharmony_ci * allocated and @root->xa_head is used as a direct slot instead of 7438c2ecf20Sopenharmony_ci * pointing to a node, in which case *@nodep will be NULL. 7448c2ecf20Sopenharmony_ci */ 7458c2ecf20Sopenharmony_civoid *__radix_tree_lookup(const struct radix_tree_root *root, 7468c2ecf20Sopenharmony_ci unsigned long index, struct radix_tree_node **nodep, 7478c2ecf20Sopenharmony_ci void __rcu ***slotp) 7488c2ecf20Sopenharmony_ci{ 7498c2ecf20Sopenharmony_ci struct radix_tree_node *node, *parent; 7508c2ecf20Sopenharmony_ci unsigned long maxindex; 7518c2ecf20Sopenharmony_ci void __rcu **slot; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci restart: 7548c2ecf20Sopenharmony_ci parent = NULL; 7558c2ecf20Sopenharmony_ci slot = (void __rcu **)&root->xa_head; 7568c2ecf20Sopenharmony_ci radix_tree_load_root(root, &node, &maxindex); 7578c2ecf20Sopenharmony_ci if (index > maxindex) 7588c2ecf20Sopenharmony_ci return NULL; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci while (radix_tree_is_internal_node(node)) { 7618c2ecf20Sopenharmony_ci unsigned offset; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci parent = entry_to_node(node); 7648c2ecf20Sopenharmony_ci offset = radix_tree_descend(parent, &node, index); 7658c2ecf20Sopenharmony_ci slot = parent->slots + offset; 7668c2ecf20Sopenharmony_ci if (node == RADIX_TREE_RETRY) 7678c2ecf20Sopenharmony_ci goto restart; 7688c2ecf20Sopenharmony_ci if (parent->shift == 0) 7698c2ecf20Sopenharmony_ci break; 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci if (nodep) 7738c2ecf20Sopenharmony_ci *nodep = parent; 7748c2ecf20Sopenharmony_ci if (slotp) 7758c2ecf20Sopenharmony_ci *slotp = slot; 7768c2ecf20Sopenharmony_ci return node; 7778c2ecf20Sopenharmony_ci} 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci/** 7808c2ecf20Sopenharmony_ci * radix_tree_lookup_slot - lookup a slot in a radix tree 7818c2ecf20Sopenharmony_ci * @root: radix tree root 7828c2ecf20Sopenharmony_ci * @index: index key 7838c2ecf20Sopenharmony_ci * 7848c2ecf20Sopenharmony_ci * Returns: the slot corresponding to the position @index in the 7858c2ecf20Sopenharmony_ci * radix tree @root. This is useful for update-if-exists operations. 7868c2ecf20Sopenharmony_ci * 7878c2ecf20Sopenharmony_ci * This function can be called under rcu_read_lock iff the slot is not 7888c2ecf20Sopenharmony_ci * modified by radix_tree_replace_slot, otherwise it must be called 7898c2ecf20Sopenharmony_ci * exclusive from other writers. Any dereference of the slot must be done 7908c2ecf20Sopenharmony_ci * using radix_tree_deref_slot. 7918c2ecf20Sopenharmony_ci */ 7928c2ecf20Sopenharmony_civoid __rcu **radix_tree_lookup_slot(const struct radix_tree_root *root, 7938c2ecf20Sopenharmony_ci unsigned long index) 7948c2ecf20Sopenharmony_ci{ 7958c2ecf20Sopenharmony_ci void __rcu **slot; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci if (!__radix_tree_lookup(root, index, NULL, &slot)) 7988c2ecf20Sopenharmony_ci return NULL; 7998c2ecf20Sopenharmony_ci return slot; 8008c2ecf20Sopenharmony_ci} 8018c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_lookup_slot); 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci/** 8048c2ecf20Sopenharmony_ci * radix_tree_lookup - perform lookup operation on a radix tree 8058c2ecf20Sopenharmony_ci * @root: radix tree root 8068c2ecf20Sopenharmony_ci * @index: index key 8078c2ecf20Sopenharmony_ci * 8088c2ecf20Sopenharmony_ci * Lookup the item at the position @index in the radix tree @root. 8098c2ecf20Sopenharmony_ci * 8108c2ecf20Sopenharmony_ci * This function can be called under rcu_read_lock, however the caller 8118c2ecf20Sopenharmony_ci * must manage lifetimes of leaf nodes (eg. RCU may also be used to free 8128c2ecf20Sopenharmony_ci * them safely). No RCU barriers are required to access or modify the 8138c2ecf20Sopenharmony_ci * returned item, however. 8148c2ecf20Sopenharmony_ci */ 8158c2ecf20Sopenharmony_civoid *radix_tree_lookup(const struct radix_tree_root *root, unsigned long index) 8168c2ecf20Sopenharmony_ci{ 8178c2ecf20Sopenharmony_ci return __radix_tree_lookup(root, index, NULL, NULL); 8188c2ecf20Sopenharmony_ci} 8198c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_lookup); 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_cistatic void replace_slot(void __rcu **slot, void *item, 8228c2ecf20Sopenharmony_ci struct radix_tree_node *node, int count, int values) 8238c2ecf20Sopenharmony_ci{ 8248c2ecf20Sopenharmony_ci if (node && (count || values)) { 8258c2ecf20Sopenharmony_ci node->count += count; 8268c2ecf20Sopenharmony_ci node->nr_values += values; 8278c2ecf20Sopenharmony_ci } 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci rcu_assign_pointer(*slot, item); 8308c2ecf20Sopenharmony_ci} 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_cistatic bool node_tag_get(const struct radix_tree_root *root, 8338c2ecf20Sopenharmony_ci const struct radix_tree_node *node, 8348c2ecf20Sopenharmony_ci unsigned int tag, unsigned int offset) 8358c2ecf20Sopenharmony_ci{ 8368c2ecf20Sopenharmony_ci if (node) 8378c2ecf20Sopenharmony_ci return tag_get(node, tag, offset); 8388c2ecf20Sopenharmony_ci return root_tag_get(root, tag); 8398c2ecf20Sopenharmony_ci} 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci/* 8428c2ecf20Sopenharmony_ci * IDR users want to be able to store NULL in the tree, so if the slot isn't 8438c2ecf20Sopenharmony_ci * free, don't adjust the count, even if it's transitioning between NULL and 8448c2ecf20Sopenharmony_ci * non-NULL. For the IDA, we mark slots as being IDR_FREE while they still 8458c2ecf20Sopenharmony_ci * have empty bits, but it only stores NULL in slots when they're being 8468c2ecf20Sopenharmony_ci * deleted. 8478c2ecf20Sopenharmony_ci */ 8488c2ecf20Sopenharmony_cistatic int calculate_count(struct radix_tree_root *root, 8498c2ecf20Sopenharmony_ci struct radix_tree_node *node, void __rcu **slot, 8508c2ecf20Sopenharmony_ci void *item, void *old) 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci if (is_idr(root)) { 8538c2ecf20Sopenharmony_ci unsigned offset = get_slot_offset(node, slot); 8548c2ecf20Sopenharmony_ci bool free = node_tag_get(root, node, IDR_FREE, offset); 8558c2ecf20Sopenharmony_ci if (!free) 8568c2ecf20Sopenharmony_ci return 0; 8578c2ecf20Sopenharmony_ci if (!old) 8588c2ecf20Sopenharmony_ci return 1; 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci return !!item - !!old; 8618c2ecf20Sopenharmony_ci} 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci/** 8648c2ecf20Sopenharmony_ci * __radix_tree_replace - replace item in a slot 8658c2ecf20Sopenharmony_ci * @root: radix tree root 8668c2ecf20Sopenharmony_ci * @node: pointer to tree node 8678c2ecf20Sopenharmony_ci * @slot: pointer to slot in @node 8688c2ecf20Sopenharmony_ci * @item: new item to store in the slot. 8698c2ecf20Sopenharmony_ci * 8708c2ecf20Sopenharmony_ci * For use with __radix_tree_lookup(). Caller must hold tree write locked 8718c2ecf20Sopenharmony_ci * across slot lookup and replacement. 8728c2ecf20Sopenharmony_ci */ 8738c2ecf20Sopenharmony_civoid __radix_tree_replace(struct radix_tree_root *root, 8748c2ecf20Sopenharmony_ci struct radix_tree_node *node, 8758c2ecf20Sopenharmony_ci void __rcu **slot, void *item) 8768c2ecf20Sopenharmony_ci{ 8778c2ecf20Sopenharmony_ci void *old = rcu_dereference_raw(*slot); 8788c2ecf20Sopenharmony_ci int values = !!xa_is_value(item) - !!xa_is_value(old); 8798c2ecf20Sopenharmony_ci int count = calculate_count(root, node, slot, item, old); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci /* 8828c2ecf20Sopenharmony_ci * This function supports replacing value entries and 8838c2ecf20Sopenharmony_ci * deleting entries, but that needs accounting against the 8848c2ecf20Sopenharmony_ci * node unless the slot is root->xa_head. 8858c2ecf20Sopenharmony_ci */ 8868c2ecf20Sopenharmony_ci WARN_ON_ONCE(!node && (slot != (void __rcu **)&root->xa_head) && 8878c2ecf20Sopenharmony_ci (count || values)); 8888c2ecf20Sopenharmony_ci replace_slot(slot, item, node, count, values); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci if (!node) 8918c2ecf20Sopenharmony_ci return; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci delete_node(root, node); 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci/** 8978c2ecf20Sopenharmony_ci * radix_tree_replace_slot - replace item in a slot 8988c2ecf20Sopenharmony_ci * @root: radix tree root 8998c2ecf20Sopenharmony_ci * @slot: pointer to slot 9008c2ecf20Sopenharmony_ci * @item: new item to store in the slot. 9018c2ecf20Sopenharmony_ci * 9028c2ecf20Sopenharmony_ci * For use with radix_tree_lookup_slot() and 9038c2ecf20Sopenharmony_ci * radix_tree_gang_lookup_tag_slot(). Caller must hold tree write locked 9048c2ecf20Sopenharmony_ci * across slot lookup and replacement. 9058c2ecf20Sopenharmony_ci * 9068c2ecf20Sopenharmony_ci * NOTE: This cannot be used to switch between non-entries (empty slots), 9078c2ecf20Sopenharmony_ci * regular entries, and value entries, as that requires accounting 9088c2ecf20Sopenharmony_ci * inside the radix tree node. When switching from one type of entry or 9098c2ecf20Sopenharmony_ci * deleting, use __radix_tree_lookup() and __radix_tree_replace() or 9108c2ecf20Sopenharmony_ci * radix_tree_iter_replace(). 9118c2ecf20Sopenharmony_ci */ 9128c2ecf20Sopenharmony_civoid radix_tree_replace_slot(struct radix_tree_root *root, 9138c2ecf20Sopenharmony_ci void __rcu **slot, void *item) 9148c2ecf20Sopenharmony_ci{ 9158c2ecf20Sopenharmony_ci __radix_tree_replace(root, NULL, slot, item); 9168c2ecf20Sopenharmony_ci} 9178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_replace_slot); 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci/** 9208c2ecf20Sopenharmony_ci * radix_tree_iter_replace - replace item in a slot 9218c2ecf20Sopenharmony_ci * @root: radix tree root 9228c2ecf20Sopenharmony_ci * @slot: pointer to slot 9238c2ecf20Sopenharmony_ci * @item: new item to store in the slot. 9248c2ecf20Sopenharmony_ci * 9258c2ecf20Sopenharmony_ci * For use with radix_tree_for_each_slot(). 9268c2ecf20Sopenharmony_ci * Caller must hold tree write locked. 9278c2ecf20Sopenharmony_ci */ 9288c2ecf20Sopenharmony_civoid radix_tree_iter_replace(struct radix_tree_root *root, 9298c2ecf20Sopenharmony_ci const struct radix_tree_iter *iter, 9308c2ecf20Sopenharmony_ci void __rcu **slot, void *item) 9318c2ecf20Sopenharmony_ci{ 9328c2ecf20Sopenharmony_ci __radix_tree_replace(root, iter->node, slot, item); 9338c2ecf20Sopenharmony_ci} 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_cistatic void node_tag_set(struct radix_tree_root *root, 9368c2ecf20Sopenharmony_ci struct radix_tree_node *node, 9378c2ecf20Sopenharmony_ci unsigned int tag, unsigned int offset) 9388c2ecf20Sopenharmony_ci{ 9398c2ecf20Sopenharmony_ci while (node) { 9408c2ecf20Sopenharmony_ci if (tag_get(node, tag, offset)) 9418c2ecf20Sopenharmony_ci return; 9428c2ecf20Sopenharmony_ci tag_set(node, tag, offset); 9438c2ecf20Sopenharmony_ci offset = node->offset; 9448c2ecf20Sopenharmony_ci node = node->parent; 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci if (!root_tag_get(root, tag)) 9488c2ecf20Sopenharmony_ci root_tag_set(root, tag); 9498c2ecf20Sopenharmony_ci} 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci/** 9528c2ecf20Sopenharmony_ci * radix_tree_tag_set - set a tag on a radix tree node 9538c2ecf20Sopenharmony_ci * @root: radix tree root 9548c2ecf20Sopenharmony_ci * @index: index key 9558c2ecf20Sopenharmony_ci * @tag: tag index 9568c2ecf20Sopenharmony_ci * 9578c2ecf20Sopenharmony_ci * Set the search tag (which must be < RADIX_TREE_MAX_TAGS) 9588c2ecf20Sopenharmony_ci * corresponding to @index in the radix tree. From 9598c2ecf20Sopenharmony_ci * the root all the way down to the leaf node. 9608c2ecf20Sopenharmony_ci * 9618c2ecf20Sopenharmony_ci * Returns the address of the tagged item. Setting a tag on a not-present 9628c2ecf20Sopenharmony_ci * item is a bug. 9638c2ecf20Sopenharmony_ci */ 9648c2ecf20Sopenharmony_civoid *radix_tree_tag_set(struct radix_tree_root *root, 9658c2ecf20Sopenharmony_ci unsigned long index, unsigned int tag) 9668c2ecf20Sopenharmony_ci{ 9678c2ecf20Sopenharmony_ci struct radix_tree_node *node, *parent; 9688c2ecf20Sopenharmony_ci unsigned long maxindex; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci radix_tree_load_root(root, &node, &maxindex); 9718c2ecf20Sopenharmony_ci BUG_ON(index > maxindex); 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci while (radix_tree_is_internal_node(node)) { 9748c2ecf20Sopenharmony_ci unsigned offset; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci parent = entry_to_node(node); 9778c2ecf20Sopenharmony_ci offset = radix_tree_descend(parent, &node, index); 9788c2ecf20Sopenharmony_ci BUG_ON(!node); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (!tag_get(parent, tag, offset)) 9818c2ecf20Sopenharmony_ci tag_set(parent, tag, offset); 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci /* set the root's tag bit */ 9858c2ecf20Sopenharmony_ci if (!root_tag_get(root, tag)) 9868c2ecf20Sopenharmony_ci root_tag_set(root, tag); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci return node; 9898c2ecf20Sopenharmony_ci} 9908c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_tag_set); 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_cistatic void node_tag_clear(struct radix_tree_root *root, 9938c2ecf20Sopenharmony_ci struct radix_tree_node *node, 9948c2ecf20Sopenharmony_ci unsigned int tag, unsigned int offset) 9958c2ecf20Sopenharmony_ci{ 9968c2ecf20Sopenharmony_ci while (node) { 9978c2ecf20Sopenharmony_ci if (!tag_get(node, tag, offset)) 9988c2ecf20Sopenharmony_ci return; 9998c2ecf20Sopenharmony_ci tag_clear(node, tag, offset); 10008c2ecf20Sopenharmony_ci if (any_tag_set(node, tag)) 10018c2ecf20Sopenharmony_ci return; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci offset = node->offset; 10048c2ecf20Sopenharmony_ci node = node->parent; 10058c2ecf20Sopenharmony_ci } 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci /* clear the root's tag bit */ 10088c2ecf20Sopenharmony_ci if (root_tag_get(root, tag)) 10098c2ecf20Sopenharmony_ci root_tag_clear(root, tag); 10108c2ecf20Sopenharmony_ci} 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci/** 10138c2ecf20Sopenharmony_ci * radix_tree_tag_clear - clear a tag on a radix tree node 10148c2ecf20Sopenharmony_ci * @root: radix tree root 10158c2ecf20Sopenharmony_ci * @index: index key 10168c2ecf20Sopenharmony_ci * @tag: tag index 10178c2ecf20Sopenharmony_ci * 10188c2ecf20Sopenharmony_ci * Clear the search tag (which must be < RADIX_TREE_MAX_TAGS) 10198c2ecf20Sopenharmony_ci * corresponding to @index in the radix tree. If this causes 10208c2ecf20Sopenharmony_ci * the leaf node to have no tags set then clear the tag in the 10218c2ecf20Sopenharmony_ci * next-to-leaf node, etc. 10228c2ecf20Sopenharmony_ci * 10238c2ecf20Sopenharmony_ci * Returns the address of the tagged item on success, else NULL. ie: 10248c2ecf20Sopenharmony_ci * has the same return value and semantics as radix_tree_lookup(). 10258c2ecf20Sopenharmony_ci */ 10268c2ecf20Sopenharmony_civoid *radix_tree_tag_clear(struct radix_tree_root *root, 10278c2ecf20Sopenharmony_ci unsigned long index, unsigned int tag) 10288c2ecf20Sopenharmony_ci{ 10298c2ecf20Sopenharmony_ci struct radix_tree_node *node, *parent; 10308c2ecf20Sopenharmony_ci unsigned long maxindex; 10318c2ecf20Sopenharmony_ci int offset; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci radix_tree_load_root(root, &node, &maxindex); 10348c2ecf20Sopenharmony_ci if (index > maxindex) 10358c2ecf20Sopenharmony_ci return NULL; 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci parent = NULL; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci while (radix_tree_is_internal_node(node)) { 10408c2ecf20Sopenharmony_ci parent = entry_to_node(node); 10418c2ecf20Sopenharmony_ci offset = radix_tree_descend(parent, &node, index); 10428c2ecf20Sopenharmony_ci } 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci if (node) 10458c2ecf20Sopenharmony_ci node_tag_clear(root, parent, tag, offset); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci return node; 10488c2ecf20Sopenharmony_ci} 10498c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_tag_clear); 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci/** 10528c2ecf20Sopenharmony_ci * radix_tree_iter_tag_clear - clear a tag on the current iterator entry 10538c2ecf20Sopenharmony_ci * @root: radix tree root 10548c2ecf20Sopenharmony_ci * @iter: iterator state 10558c2ecf20Sopenharmony_ci * @tag: tag to clear 10568c2ecf20Sopenharmony_ci */ 10578c2ecf20Sopenharmony_civoid radix_tree_iter_tag_clear(struct radix_tree_root *root, 10588c2ecf20Sopenharmony_ci const struct radix_tree_iter *iter, unsigned int tag) 10598c2ecf20Sopenharmony_ci{ 10608c2ecf20Sopenharmony_ci node_tag_clear(root, iter->node, tag, iter_offset(iter)); 10618c2ecf20Sopenharmony_ci} 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci/** 10648c2ecf20Sopenharmony_ci * radix_tree_tag_get - get a tag on a radix tree node 10658c2ecf20Sopenharmony_ci * @root: radix tree root 10668c2ecf20Sopenharmony_ci * @index: index key 10678c2ecf20Sopenharmony_ci * @tag: tag index (< RADIX_TREE_MAX_TAGS) 10688c2ecf20Sopenharmony_ci * 10698c2ecf20Sopenharmony_ci * Return values: 10708c2ecf20Sopenharmony_ci * 10718c2ecf20Sopenharmony_ci * 0: tag not present or not set 10728c2ecf20Sopenharmony_ci * 1: tag set 10738c2ecf20Sopenharmony_ci * 10748c2ecf20Sopenharmony_ci * Note that the return value of this function may not be relied on, even if 10758c2ecf20Sopenharmony_ci * the RCU lock is held, unless tag modification and node deletion are excluded 10768c2ecf20Sopenharmony_ci * from concurrency. 10778c2ecf20Sopenharmony_ci */ 10788c2ecf20Sopenharmony_ciint radix_tree_tag_get(const struct radix_tree_root *root, 10798c2ecf20Sopenharmony_ci unsigned long index, unsigned int tag) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci struct radix_tree_node *node, *parent; 10828c2ecf20Sopenharmony_ci unsigned long maxindex; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci if (!root_tag_get(root, tag)) 10858c2ecf20Sopenharmony_ci return 0; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci radix_tree_load_root(root, &node, &maxindex); 10888c2ecf20Sopenharmony_ci if (index > maxindex) 10898c2ecf20Sopenharmony_ci return 0; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci while (radix_tree_is_internal_node(node)) { 10928c2ecf20Sopenharmony_ci unsigned offset; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci parent = entry_to_node(node); 10958c2ecf20Sopenharmony_ci offset = radix_tree_descend(parent, &node, index); 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci if (!tag_get(parent, tag, offset)) 10988c2ecf20Sopenharmony_ci return 0; 10998c2ecf20Sopenharmony_ci if (node == RADIX_TREE_RETRY) 11008c2ecf20Sopenharmony_ci break; 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci return 1; 11048c2ecf20Sopenharmony_ci} 11058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_tag_get); 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci/* Construct iter->tags bit-mask from node->tags[tag] array */ 11088c2ecf20Sopenharmony_cistatic void set_iter_tags(struct radix_tree_iter *iter, 11098c2ecf20Sopenharmony_ci struct radix_tree_node *node, unsigned offset, 11108c2ecf20Sopenharmony_ci unsigned tag) 11118c2ecf20Sopenharmony_ci{ 11128c2ecf20Sopenharmony_ci unsigned tag_long = offset / BITS_PER_LONG; 11138c2ecf20Sopenharmony_ci unsigned tag_bit = offset % BITS_PER_LONG; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci if (!node) { 11168c2ecf20Sopenharmony_ci iter->tags = 1; 11178c2ecf20Sopenharmony_ci return; 11188c2ecf20Sopenharmony_ci } 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci iter->tags = node->tags[tag][tag_long] >> tag_bit; 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci /* This never happens if RADIX_TREE_TAG_LONGS == 1 */ 11238c2ecf20Sopenharmony_ci if (tag_long < RADIX_TREE_TAG_LONGS - 1) { 11248c2ecf20Sopenharmony_ci /* Pick tags from next element */ 11258c2ecf20Sopenharmony_ci if (tag_bit) 11268c2ecf20Sopenharmony_ci iter->tags |= node->tags[tag][tag_long + 1] << 11278c2ecf20Sopenharmony_ci (BITS_PER_LONG - tag_bit); 11288c2ecf20Sopenharmony_ci /* Clip chunk size, here only BITS_PER_LONG tags */ 11298c2ecf20Sopenharmony_ci iter->next_index = __radix_tree_iter_add(iter, BITS_PER_LONG); 11308c2ecf20Sopenharmony_ci } 11318c2ecf20Sopenharmony_ci} 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_civoid __rcu **radix_tree_iter_resume(void __rcu **slot, 11348c2ecf20Sopenharmony_ci struct radix_tree_iter *iter) 11358c2ecf20Sopenharmony_ci{ 11368c2ecf20Sopenharmony_ci iter->index = __radix_tree_iter_add(iter, 1); 11378c2ecf20Sopenharmony_ci iter->next_index = iter->index; 11388c2ecf20Sopenharmony_ci iter->tags = 0; 11398c2ecf20Sopenharmony_ci return NULL; 11408c2ecf20Sopenharmony_ci} 11418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_iter_resume); 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci/** 11448c2ecf20Sopenharmony_ci * radix_tree_next_chunk - find next chunk of slots for iteration 11458c2ecf20Sopenharmony_ci * 11468c2ecf20Sopenharmony_ci * @root: radix tree root 11478c2ecf20Sopenharmony_ci * @iter: iterator state 11488c2ecf20Sopenharmony_ci * @flags: RADIX_TREE_ITER_* flags and tag index 11498c2ecf20Sopenharmony_ci * Returns: pointer to chunk first slot, or NULL if iteration is over 11508c2ecf20Sopenharmony_ci */ 11518c2ecf20Sopenharmony_civoid __rcu **radix_tree_next_chunk(const struct radix_tree_root *root, 11528c2ecf20Sopenharmony_ci struct radix_tree_iter *iter, unsigned flags) 11538c2ecf20Sopenharmony_ci{ 11548c2ecf20Sopenharmony_ci unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK; 11558c2ecf20Sopenharmony_ci struct radix_tree_node *node, *child; 11568c2ecf20Sopenharmony_ci unsigned long index, offset, maxindex; 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag)) 11598c2ecf20Sopenharmony_ci return NULL; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci /* 11628c2ecf20Sopenharmony_ci * Catch next_index overflow after ~0UL. iter->index never overflows 11638c2ecf20Sopenharmony_ci * during iterating; it can be zero only at the beginning. 11648c2ecf20Sopenharmony_ci * And we cannot overflow iter->next_index in a single step, 11658c2ecf20Sopenharmony_ci * because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG. 11668c2ecf20Sopenharmony_ci * 11678c2ecf20Sopenharmony_ci * This condition also used by radix_tree_next_slot() to stop 11688c2ecf20Sopenharmony_ci * contiguous iterating, and forbid switching to the next chunk. 11698c2ecf20Sopenharmony_ci */ 11708c2ecf20Sopenharmony_ci index = iter->next_index; 11718c2ecf20Sopenharmony_ci if (!index && iter->index) 11728c2ecf20Sopenharmony_ci return NULL; 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci restart: 11758c2ecf20Sopenharmony_ci radix_tree_load_root(root, &child, &maxindex); 11768c2ecf20Sopenharmony_ci if (index > maxindex) 11778c2ecf20Sopenharmony_ci return NULL; 11788c2ecf20Sopenharmony_ci if (!child) 11798c2ecf20Sopenharmony_ci return NULL; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci if (!radix_tree_is_internal_node(child)) { 11828c2ecf20Sopenharmony_ci /* Single-slot tree */ 11838c2ecf20Sopenharmony_ci iter->index = index; 11848c2ecf20Sopenharmony_ci iter->next_index = maxindex + 1; 11858c2ecf20Sopenharmony_ci iter->tags = 1; 11868c2ecf20Sopenharmony_ci iter->node = NULL; 11878c2ecf20Sopenharmony_ci return (void __rcu **)&root->xa_head; 11888c2ecf20Sopenharmony_ci } 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci do { 11918c2ecf20Sopenharmony_ci node = entry_to_node(child); 11928c2ecf20Sopenharmony_ci offset = radix_tree_descend(node, &child, index); 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci if ((flags & RADIX_TREE_ITER_TAGGED) ? 11958c2ecf20Sopenharmony_ci !tag_get(node, tag, offset) : !child) { 11968c2ecf20Sopenharmony_ci /* Hole detected */ 11978c2ecf20Sopenharmony_ci if (flags & RADIX_TREE_ITER_CONTIG) 11988c2ecf20Sopenharmony_ci return NULL; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci if (flags & RADIX_TREE_ITER_TAGGED) 12018c2ecf20Sopenharmony_ci offset = radix_tree_find_next_bit(node, tag, 12028c2ecf20Sopenharmony_ci offset + 1); 12038c2ecf20Sopenharmony_ci else 12048c2ecf20Sopenharmony_ci while (++offset < RADIX_TREE_MAP_SIZE) { 12058c2ecf20Sopenharmony_ci void *slot = rcu_dereference_raw( 12068c2ecf20Sopenharmony_ci node->slots[offset]); 12078c2ecf20Sopenharmony_ci if (slot) 12088c2ecf20Sopenharmony_ci break; 12098c2ecf20Sopenharmony_ci } 12108c2ecf20Sopenharmony_ci index &= ~node_maxindex(node); 12118c2ecf20Sopenharmony_ci index += offset << node->shift; 12128c2ecf20Sopenharmony_ci /* Overflow after ~0UL */ 12138c2ecf20Sopenharmony_ci if (!index) 12148c2ecf20Sopenharmony_ci return NULL; 12158c2ecf20Sopenharmony_ci if (offset == RADIX_TREE_MAP_SIZE) 12168c2ecf20Sopenharmony_ci goto restart; 12178c2ecf20Sopenharmony_ci child = rcu_dereference_raw(node->slots[offset]); 12188c2ecf20Sopenharmony_ci } 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci if (!child) 12218c2ecf20Sopenharmony_ci goto restart; 12228c2ecf20Sopenharmony_ci if (child == RADIX_TREE_RETRY) 12238c2ecf20Sopenharmony_ci break; 12248c2ecf20Sopenharmony_ci } while (node->shift && radix_tree_is_internal_node(child)); 12258c2ecf20Sopenharmony_ci 12268c2ecf20Sopenharmony_ci /* Update the iterator state */ 12278c2ecf20Sopenharmony_ci iter->index = (index &~ node_maxindex(node)) | offset; 12288c2ecf20Sopenharmony_ci iter->next_index = (index | node_maxindex(node)) + 1; 12298c2ecf20Sopenharmony_ci iter->node = node; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci if (flags & RADIX_TREE_ITER_TAGGED) 12328c2ecf20Sopenharmony_ci set_iter_tags(iter, node, offset, tag); 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci return node->slots + offset; 12358c2ecf20Sopenharmony_ci} 12368c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_next_chunk); 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci/** 12398c2ecf20Sopenharmony_ci * radix_tree_gang_lookup - perform multiple lookup on a radix tree 12408c2ecf20Sopenharmony_ci * @root: radix tree root 12418c2ecf20Sopenharmony_ci * @results: where the results of the lookup are placed 12428c2ecf20Sopenharmony_ci * @first_index: start the lookup from this key 12438c2ecf20Sopenharmony_ci * @max_items: place up to this many items at *results 12448c2ecf20Sopenharmony_ci * 12458c2ecf20Sopenharmony_ci * Performs an index-ascending scan of the tree for present items. Places 12468c2ecf20Sopenharmony_ci * them at *@results and returns the number of items which were placed at 12478c2ecf20Sopenharmony_ci * *@results. 12488c2ecf20Sopenharmony_ci * 12498c2ecf20Sopenharmony_ci * The implementation is naive. 12508c2ecf20Sopenharmony_ci * 12518c2ecf20Sopenharmony_ci * Like radix_tree_lookup, radix_tree_gang_lookup may be called under 12528c2ecf20Sopenharmony_ci * rcu_read_lock. In this case, rather than the returned results being 12538c2ecf20Sopenharmony_ci * an atomic snapshot of the tree at a single point in time, the 12548c2ecf20Sopenharmony_ci * semantics of an RCU protected gang lookup are as though multiple 12558c2ecf20Sopenharmony_ci * radix_tree_lookups have been issued in individual locks, and results 12568c2ecf20Sopenharmony_ci * stored in 'results'. 12578c2ecf20Sopenharmony_ci */ 12588c2ecf20Sopenharmony_ciunsigned int 12598c2ecf20Sopenharmony_ciradix_tree_gang_lookup(const struct radix_tree_root *root, void **results, 12608c2ecf20Sopenharmony_ci unsigned long first_index, unsigned int max_items) 12618c2ecf20Sopenharmony_ci{ 12628c2ecf20Sopenharmony_ci struct radix_tree_iter iter; 12638c2ecf20Sopenharmony_ci void __rcu **slot; 12648c2ecf20Sopenharmony_ci unsigned int ret = 0; 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci if (unlikely(!max_items)) 12678c2ecf20Sopenharmony_ci return 0; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci radix_tree_for_each_slot(slot, root, &iter, first_index) { 12708c2ecf20Sopenharmony_ci results[ret] = rcu_dereference_raw(*slot); 12718c2ecf20Sopenharmony_ci if (!results[ret]) 12728c2ecf20Sopenharmony_ci continue; 12738c2ecf20Sopenharmony_ci if (radix_tree_is_internal_node(results[ret])) { 12748c2ecf20Sopenharmony_ci slot = radix_tree_iter_retry(&iter); 12758c2ecf20Sopenharmony_ci continue; 12768c2ecf20Sopenharmony_ci } 12778c2ecf20Sopenharmony_ci if (++ret == max_items) 12788c2ecf20Sopenharmony_ci break; 12798c2ecf20Sopenharmony_ci } 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci return ret; 12828c2ecf20Sopenharmony_ci} 12838c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_gang_lookup); 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci/** 12868c2ecf20Sopenharmony_ci * radix_tree_gang_lookup_tag - perform multiple lookup on a radix tree 12878c2ecf20Sopenharmony_ci * based on a tag 12888c2ecf20Sopenharmony_ci * @root: radix tree root 12898c2ecf20Sopenharmony_ci * @results: where the results of the lookup are placed 12908c2ecf20Sopenharmony_ci * @first_index: start the lookup from this key 12918c2ecf20Sopenharmony_ci * @max_items: place up to this many items at *results 12928c2ecf20Sopenharmony_ci * @tag: the tag index (< RADIX_TREE_MAX_TAGS) 12938c2ecf20Sopenharmony_ci * 12948c2ecf20Sopenharmony_ci * Performs an index-ascending scan of the tree for present items which 12958c2ecf20Sopenharmony_ci * have the tag indexed by @tag set. Places the items at *@results and 12968c2ecf20Sopenharmony_ci * returns the number of items which were placed at *@results. 12978c2ecf20Sopenharmony_ci */ 12988c2ecf20Sopenharmony_ciunsigned int 12998c2ecf20Sopenharmony_ciradix_tree_gang_lookup_tag(const struct radix_tree_root *root, void **results, 13008c2ecf20Sopenharmony_ci unsigned long first_index, unsigned int max_items, 13018c2ecf20Sopenharmony_ci unsigned int tag) 13028c2ecf20Sopenharmony_ci{ 13038c2ecf20Sopenharmony_ci struct radix_tree_iter iter; 13048c2ecf20Sopenharmony_ci void __rcu **slot; 13058c2ecf20Sopenharmony_ci unsigned int ret = 0; 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci if (unlikely(!max_items)) 13088c2ecf20Sopenharmony_ci return 0; 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) { 13118c2ecf20Sopenharmony_ci results[ret] = rcu_dereference_raw(*slot); 13128c2ecf20Sopenharmony_ci if (!results[ret]) 13138c2ecf20Sopenharmony_ci continue; 13148c2ecf20Sopenharmony_ci if (radix_tree_is_internal_node(results[ret])) { 13158c2ecf20Sopenharmony_ci slot = radix_tree_iter_retry(&iter); 13168c2ecf20Sopenharmony_ci continue; 13178c2ecf20Sopenharmony_ci } 13188c2ecf20Sopenharmony_ci if (++ret == max_items) 13198c2ecf20Sopenharmony_ci break; 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci return ret; 13238c2ecf20Sopenharmony_ci} 13248c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_gang_lookup_tag); 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci/** 13278c2ecf20Sopenharmony_ci * radix_tree_gang_lookup_tag_slot - perform multiple slot lookup on a 13288c2ecf20Sopenharmony_ci * radix tree based on a tag 13298c2ecf20Sopenharmony_ci * @root: radix tree root 13308c2ecf20Sopenharmony_ci * @results: where the results of the lookup are placed 13318c2ecf20Sopenharmony_ci * @first_index: start the lookup from this key 13328c2ecf20Sopenharmony_ci * @max_items: place up to this many items at *results 13338c2ecf20Sopenharmony_ci * @tag: the tag index (< RADIX_TREE_MAX_TAGS) 13348c2ecf20Sopenharmony_ci * 13358c2ecf20Sopenharmony_ci * Performs an index-ascending scan of the tree for present items which 13368c2ecf20Sopenharmony_ci * have the tag indexed by @tag set. Places the slots at *@results and 13378c2ecf20Sopenharmony_ci * returns the number of slots which were placed at *@results. 13388c2ecf20Sopenharmony_ci */ 13398c2ecf20Sopenharmony_ciunsigned int 13408c2ecf20Sopenharmony_ciradix_tree_gang_lookup_tag_slot(const struct radix_tree_root *root, 13418c2ecf20Sopenharmony_ci void __rcu ***results, unsigned long first_index, 13428c2ecf20Sopenharmony_ci unsigned int max_items, unsigned int tag) 13438c2ecf20Sopenharmony_ci{ 13448c2ecf20Sopenharmony_ci struct radix_tree_iter iter; 13458c2ecf20Sopenharmony_ci void __rcu **slot; 13468c2ecf20Sopenharmony_ci unsigned int ret = 0; 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci if (unlikely(!max_items)) 13498c2ecf20Sopenharmony_ci return 0; 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) { 13528c2ecf20Sopenharmony_ci results[ret] = slot; 13538c2ecf20Sopenharmony_ci if (++ret == max_items) 13548c2ecf20Sopenharmony_ci break; 13558c2ecf20Sopenharmony_ci } 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci return ret; 13588c2ecf20Sopenharmony_ci} 13598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_gang_lookup_tag_slot); 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_cistatic bool __radix_tree_delete(struct radix_tree_root *root, 13628c2ecf20Sopenharmony_ci struct radix_tree_node *node, void __rcu **slot) 13638c2ecf20Sopenharmony_ci{ 13648c2ecf20Sopenharmony_ci void *old = rcu_dereference_raw(*slot); 13658c2ecf20Sopenharmony_ci int values = xa_is_value(old) ? -1 : 0; 13668c2ecf20Sopenharmony_ci unsigned offset = get_slot_offset(node, slot); 13678c2ecf20Sopenharmony_ci int tag; 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci if (is_idr(root)) 13708c2ecf20Sopenharmony_ci node_tag_set(root, node, IDR_FREE, offset); 13718c2ecf20Sopenharmony_ci else 13728c2ecf20Sopenharmony_ci for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) 13738c2ecf20Sopenharmony_ci node_tag_clear(root, node, tag, offset); 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci replace_slot(slot, NULL, node, -1, values); 13768c2ecf20Sopenharmony_ci return node && delete_node(root, node); 13778c2ecf20Sopenharmony_ci} 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci/** 13808c2ecf20Sopenharmony_ci * radix_tree_iter_delete - delete the entry at this iterator position 13818c2ecf20Sopenharmony_ci * @root: radix tree root 13828c2ecf20Sopenharmony_ci * @iter: iterator state 13838c2ecf20Sopenharmony_ci * @slot: pointer to slot 13848c2ecf20Sopenharmony_ci * 13858c2ecf20Sopenharmony_ci * Delete the entry at the position currently pointed to by the iterator. 13868c2ecf20Sopenharmony_ci * This may result in the current node being freed; if it is, the iterator 13878c2ecf20Sopenharmony_ci * is advanced so that it will not reference the freed memory. This 13888c2ecf20Sopenharmony_ci * function may be called without any locking if there are no other threads 13898c2ecf20Sopenharmony_ci * which can access this tree. 13908c2ecf20Sopenharmony_ci */ 13918c2ecf20Sopenharmony_civoid radix_tree_iter_delete(struct radix_tree_root *root, 13928c2ecf20Sopenharmony_ci struct radix_tree_iter *iter, void __rcu **slot) 13938c2ecf20Sopenharmony_ci{ 13948c2ecf20Sopenharmony_ci if (__radix_tree_delete(root, iter->node, slot)) 13958c2ecf20Sopenharmony_ci iter->index = iter->next_index; 13968c2ecf20Sopenharmony_ci} 13978c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_iter_delete); 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci/** 14008c2ecf20Sopenharmony_ci * radix_tree_delete_item - delete an item from a radix tree 14018c2ecf20Sopenharmony_ci * @root: radix tree root 14028c2ecf20Sopenharmony_ci * @index: index key 14038c2ecf20Sopenharmony_ci * @item: expected item 14048c2ecf20Sopenharmony_ci * 14058c2ecf20Sopenharmony_ci * Remove @item at @index from the radix tree rooted at @root. 14068c2ecf20Sopenharmony_ci * 14078c2ecf20Sopenharmony_ci * Return: the deleted entry, or %NULL if it was not present 14088c2ecf20Sopenharmony_ci * or the entry at the given @index was not @item. 14098c2ecf20Sopenharmony_ci */ 14108c2ecf20Sopenharmony_civoid *radix_tree_delete_item(struct radix_tree_root *root, 14118c2ecf20Sopenharmony_ci unsigned long index, void *item) 14128c2ecf20Sopenharmony_ci{ 14138c2ecf20Sopenharmony_ci struct radix_tree_node *node = NULL; 14148c2ecf20Sopenharmony_ci void __rcu **slot = NULL; 14158c2ecf20Sopenharmony_ci void *entry; 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci entry = __radix_tree_lookup(root, index, &node, &slot); 14188c2ecf20Sopenharmony_ci if (!slot) 14198c2ecf20Sopenharmony_ci return NULL; 14208c2ecf20Sopenharmony_ci if (!entry && (!is_idr(root) || node_tag_get(root, node, IDR_FREE, 14218c2ecf20Sopenharmony_ci get_slot_offset(node, slot)))) 14228c2ecf20Sopenharmony_ci return NULL; 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ci if (item && entry != item) 14258c2ecf20Sopenharmony_ci return NULL; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci __radix_tree_delete(root, node, slot); 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci return entry; 14308c2ecf20Sopenharmony_ci} 14318c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_delete_item); 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci/** 14348c2ecf20Sopenharmony_ci * radix_tree_delete - delete an entry from a radix tree 14358c2ecf20Sopenharmony_ci * @root: radix tree root 14368c2ecf20Sopenharmony_ci * @index: index key 14378c2ecf20Sopenharmony_ci * 14388c2ecf20Sopenharmony_ci * Remove the entry at @index from the radix tree rooted at @root. 14398c2ecf20Sopenharmony_ci * 14408c2ecf20Sopenharmony_ci * Return: The deleted entry, or %NULL if it was not present. 14418c2ecf20Sopenharmony_ci */ 14428c2ecf20Sopenharmony_civoid *radix_tree_delete(struct radix_tree_root *root, unsigned long index) 14438c2ecf20Sopenharmony_ci{ 14448c2ecf20Sopenharmony_ci return radix_tree_delete_item(root, index, NULL); 14458c2ecf20Sopenharmony_ci} 14468c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_delete); 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci/** 14498c2ecf20Sopenharmony_ci * radix_tree_tagged - test whether any items in the tree are tagged 14508c2ecf20Sopenharmony_ci * @root: radix tree root 14518c2ecf20Sopenharmony_ci * @tag: tag to test 14528c2ecf20Sopenharmony_ci */ 14538c2ecf20Sopenharmony_ciint radix_tree_tagged(const struct radix_tree_root *root, unsigned int tag) 14548c2ecf20Sopenharmony_ci{ 14558c2ecf20Sopenharmony_ci return root_tag_get(root, tag); 14568c2ecf20Sopenharmony_ci} 14578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(radix_tree_tagged); 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci/** 14608c2ecf20Sopenharmony_ci * idr_preload - preload for idr_alloc() 14618c2ecf20Sopenharmony_ci * @gfp_mask: allocation mask to use for preloading 14628c2ecf20Sopenharmony_ci * 14638c2ecf20Sopenharmony_ci * Preallocate memory to use for the next call to idr_alloc(). This function 14648c2ecf20Sopenharmony_ci * returns with preemption disabled. It will be enabled by idr_preload_end(). 14658c2ecf20Sopenharmony_ci */ 14668c2ecf20Sopenharmony_civoid idr_preload(gfp_t gfp_mask) 14678c2ecf20Sopenharmony_ci{ 14688c2ecf20Sopenharmony_ci if (__radix_tree_preload(gfp_mask, IDR_PRELOAD_SIZE)) 14698c2ecf20Sopenharmony_ci local_lock(&radix_tree_preloads.lock); 14708c2ecf20Sopenharmony_ci} 14718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(idr_preload); 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_civoid __rcu **idr_get_free(struct radix_tree_root *root, 14748c2ecf20Sopenharmony_ci struct radix_tree_iter *iter, gfp_t gfp, 14758c2ecf20Sopenharmony_ci unsigned long max) 14768c2ecf20Sopenharmony_ci{ 14778c2ecf20Sopenharmony_ci struct radix_tree_node *node = NULL, *child; 14788c2ecf20Sopenharmony_ci void __rcu **slot = (void __rcu **)&root->xa_head; 14798c2ecf20Sopenharmony_ci unsigned long maxindex, start = iter->next_index; 14808c2ecf20Sopenharmony_ci unsigned int shift, offset = 0; 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci grow: 14838c2ecf20Sopenharmony_ci shift = radix_tree_load_root(root, &child, &maxindex); 14848c2ecf20Sopenharmony_ci if (!radix_tree_tagged(root, IDR_FREE)) 14858c2ecf20Sopenharmony_ci start = max(start, maxindex + 1); 14868c2ecf20Sopenharmony_ci if (start > max) 14878c2ecf20Sopenharmony_ci return ERR_PTR(-ENOSPC); 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci if (start > maxindex) { 14908c2ecf20Sopenharmony_ci int error = radix_tree_extend(root, gfp, start, shift); 14918c2ecf20Sopenharmony_ci if (error < 0) 14928c2ecf20Sopenharmony_ci return ERR_PTR(error); 14938c2ecf20Sopenharmony_ci shift = error; 14948c2ecf20Sopenharmony_ci child = rcu_dereference_raw(root->xa_head); 14958c2ecf20Sopenharmony_ci } 14968c2ecf20Sopenharmony_ci if (start == 0 && shift == 0) 14978c2ecf20Sopenharmony_ci shift = RADIX_TREE_MAP_SHIFT; 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci while (shift) { 15008c2ecf20Sopenharmony_ci shift -= RADIX_TREE_MAP_SHIFT; 15018c2ecf20Sopenharmony_ci if (child == NULL) { 15028c2ecf20Sopenharmony_ci /* Have to add a child node. */ 15038c2ecf20Sopenharmony_ci child = radix_tree_node_alloc(gfp, node, root, shift, 15048c2ecf20Sopenharmony_ci offset, 0, 0); 15058c2ecf20Sopenharmony_ci if (!child) 15068c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 15078c2ecf20Sopenharmony_ci all_tag_set(child, IDR_FREE); 15088c2ecf20Sopenharmony_ci rcu_assign_pointer(*slot, node_to_entry(child)); 15098c2ecf20Sopenharmony_ci if (node) 15108c2ecf20Sopenharmony_ci node->count++; 15118c2ecf20Sopenharmony_ci } else if (!radix_tree_is_internal_node(child)) 15128c2ecf20Sopenharmony_ci break; 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci node = entry_to_node(child); 15158c2ecf20Sopenharmony_ci offset = radix_tree_descend(node, &child, start); 15168c2ecf20Sopenharmony_ci if (!tag_get(node, IDR_FREE, offset)) { 15178c2ecf20Sopenharmony_ci offset = radix_tree_find_next_bit(node, IDR_FREE, 15188c2ecf20Sopenharmony_ci offset + 1); 15198c2ecf20Sopenharmony_ci start = next_index(start, node, offset); 15208c2ecf20Sopenharmony_ci if (start > max || start == 0) 15218c2ecf20Sopenharmony_ci return ERR_PTR(-ENOSPC); 15228c2ecf20Sopenharmony_ci while (offset == RADIX_TREE_MAP_SIZE) { 15238c2ecf20Sopenharmony_ci offset = node->offset + 1; 15248c2ecf20Sopenharmony_ci node = node->parent; 15258c2ecf20Sopenharmony_ci if (!node) 15268c2ecf20Sopenharmony_ci goto grow; 15278c2ecf20Sopenharmony_ci shift = node->shift; 15288c2ecf20Sopenharmony_ci } 15298c2ecf20Sopenharmony_ci child = rcu_dereference_raw(node->slots[offset]); 15308c2ecf20Sopenharmony_ci } 15318c2ecf20Sopenharmony_ci slot = &node->slots[offset]; 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci iter->index = start; 15358c2ecf20Sopenharmony_ci if (node) 15368c2ecf20Sopenharmony_ci iter->next_index = 1 + min(max, (start | node_maxindex(node))); 15378c2ecf20Sopenharmony_ci else 15388c2ecf20Sopenharmony_ci iter->next_index = 1; 15398c2ecf20Sopenharmony_ci iter->node = node; 15408c2ecf20Sopenharmony_ci set_iter_tags(iter, node, offset, IDR_FREE); 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci return slot; 15438c2ecf20Sopenharmony_ci} 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci/** 15468c2ecf20Sopenharmony_ci * idr_destroy - release all internal memory from an IDR 15478c2ecf20Sopenharmony_ci * @idr: idr handle 15488c2ecf20Sopenharmony_ci * 15498c2ecf20Sopenharmony_ci * After this function is called, the IDR is empty, and may be reused or 15508c2ecf20Sopenharmony_ci * the data structure containing it may be freed. 15518c2ecf20Sopenharmony_ci * 15528c2ecf20Sopenharmony_ci * A typical clean-up sequence for objects stored in an idr tree will use 15538c2ecf20Sopenharmony_ci * idr_for_each() to free all objects, if necessary, then idr_destroy() to 15548c2ecf20Sopenharmony_ci * free the memory used to keep track of those objects. 15558c2ecf20Sopenharmony_ci */ 15568c2ecf20Sopenharmony_civoid idr_destroy(struct idr *idr) 15578c2ecf20Sopenharmony_ci{ 15588c2ecf20Sopenharmony_ci struct radix_tree_node *node = rcu_dereference_raw(idr->idr_rt.xa_head); 15598c2ecf20Sopenharmony_ci if (radix_tree_is_internal_node(node)) 15608c2ecf20Sopenharmony_ci radix_tree_free_nodes(node); 15618c2ecf20Sopenharmony_ci idr->idr_rt.xa_head = NULL; 15628c2ecf20Sopenharmony_ci root_tag_set(&idr->idr_rt, IDR_FREE); 15638c2ecf20Sopenharmony_ci} 15648c2ecf20Sopenharmony_ciEXPORT_SYMBOL(idr_destroy); 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_cistatic void 15678c2ecf20Sopenharmony_ciradix_tree_node_ctor(void *arg) 15688c2ecf20Sopenharmony_ci{ 15698c2ecf20Sopenharmony_ci struct radix_tree_node *node = arg; 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci memset(node, 0, sizeof(*node)); 15728c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&node->private_list); 15738c2ecf20Sopenharmony_ci} 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_cistatic int radix_tree_cpu_dead(unsigned int cpu) 15768c2ecf20Sopenharmony_ci{ 15778c2ecf20Sopenharmony_ci struct radix_tree_preload *rtp; 15788c2ecf20Sopenharmony_ci struct radix_tree_node *node; 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci /* Free per-cpu pool of preloaded nodes */ 15818c2ecf20Sopenharmony_ci rtp = &per_cpu(radix_tree_preloads, cpu); 15828c2ecf20Sopenharmony_ci while (rtp->nr) { 15838c2ecf20Sopenharmony_ci node = rtp->nodes; 15848c2ecf20Sopenharmony_ci rtp->nodes = node->parent; 15858c2ecf20Sopenharmony_ci kmem_cache_free(radix_tree_node_cachep, node); 15868c2ecf20Sopenharmony_ci rtp->nr--; 15878c2ecf20Sopenharmony_ci } 15888c2ecf20Sopenharmony_ci return 0; 15898c2ecf20Sopenharmony_ci} 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_civoid __init radix_tree_init(void) 15928c2ecf20Sopenharmony_ci{ 15938c2ecf20Sopenharmony_ci int ret; 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci BUILD_BUG_ON(RADIX_TREE_MAX_TAGS + __GFP_BITS_SHIFT > 32); 15968c2ecf20Sopenharmony_ci BUILD_BUG_ON(ROOT_IS_IDR & ~GFP_ZONEMASK); 15978c2ecf20Sopenharmony_ci BUILD_BUG_ON(XA_CHUNK_SIZE > 255); 15988c2ecf20Sopenharmony_ci radix_tree_node_cachep = kmem_cache_create("radix_tree_node", 15998c2ecf20Sopenharmony_ci sizeof(struct radix_tree_node), 0, 16008c2ecf20Sopenharmony_ci SLAB_PANIC | SLAB_RECLAIM_ACCOUNT, 16018c2ecf20Sopenharmony_ci radix_tree_node_ctor); 16028c2ecf20Sopenharmony_ci ret = cpuhp_setup_state_nocalls(CPUHP_RADIX_DEAD, "lib/radix:dead", 16038c2ecf20Sopenharmony_ci NULL, radix_tree_cpu_dead); 16048c2ecf20Sopenharmony_ci WARN_ON(ret < 0); 16058c2ecf20Sopenharmony_ci} 1606