Branch data Line data Source code
1 : : 2 : : #include <linux/export.h> 3 : : #include <linux/generic-radix-tree.h> 4 : : #include <linux/gfp.h> 5 : : #include <linux/kmemleak.h> 6 : : 7 : : #define GENRADIX_ARY (PAGE_SIZE / sizeof(struct genradix_node *)) 8 : : #define GENRADIX_ARY_SHIFT ilog2(GENRADIX_ARY) 9 : : 10 : : struct genradix_node { 11 : : union { 12 : : /* Interior node: */ 13 : : struct genradix_node *children[GENRADIX_ARY]; 14 : : 15 : : /* Leaf: */ 16 : : u8 data[PAGE_SIZE]; 17 : : }; 18 : : }; 19 : : 20 : : static inline int genradix_depth_shift(unsigned depth) 21 : : { 22 : 0 : return PAGE_SHIFT + GENRADIX_ARY_SHIFT * depth; 23 : : } 24 : : 25 : : /* 26 : : * Returns size (of data, in bytes) that a tree of a given depth holds: 27 : : */ 28 : : static inline size_t genradix_depth_size(unsigned depth) 29 : : { 30 : 0 : return 1UL << genradix_depth_shift(depth); 31 : : } 32 : : 33 : : /* depth that's needed for a genradix that can address up to ULONG_MAX: */ 34 : : #define GENRADIX_MAX_DEPTH \ 35 : : DIV_ROUND_UP(BITS_PER_LONG - PAGE_SHIFT, GENRADIX_ARY_SHIFT) 36 : : 37 : : #define GENRADIX_DEPTH_MASK \ 38 : : ((unsigned long) (roundup_pow_of_two(GENRADIX_MAX_DEPTH + 1) - 1)) 39 : : 40 : : static inline unsigned genradix_root_to_depth(struct genradix_root *r) 41 : : { 42 : 0 : return (unsigned long) r & GENRADIX_DEPTH_MASK; 43 : : } 44 : : 45 : : static inline struct genradix_node *genradix_root_to_node(struct genradix_root *r) 46 : : { 47 : 0 : return (void *) ((unsigned long) r & ~GENRADIX_DEPTH_MASK); 48 : : } 49 : : 50 : : /* 51 : : * Returns pointer to the specified byte @offset within @radix, or NULL if not 52 : : * allocated 53 : : */ 54 : 0 : void *__genradix_ptr(struct __genradix *radix, size_t offset) 55 : : { 56 : : struct genradix_root *r = READ_ONCE(radix->root); 57 : : struct genradix_node *n = genradix_root_to_node(r); 58 : : unsigned level = genradix_root_to_depth(r); 59 : : 60 : 0 : if (ilog2(offset) >= genradix_depth_shift(level)) 61 : : return NULL; 62 : : 63 : : while (1) { 64 : 0 : if (!n) 65 : : return NULL; 66 : 0 : if (!level) 67 : : break; 68 : : 69 : 0 : level--; 70 : : 71 : 0 : n = n->children[offset >> genradix_depth_shift(level)]; 72 : 0 : offset &= genradix_depth_size(level) - 1; 73 : 0 : } 74 : : 75 : 0 : return &n->data[offset]; 76 : : } 77 : : EXPORT_SYMBOL(__genradix_ptr); 78 : : 79 : : static inline struct genradix_node *genradix_alloc_node(gfp_t gfp_mask) 80 : : { 81 : : struct genradix_node *node; 82 : : 83 : 0 : node = (struct genradix_node *)__get_free_page(gfp_mask|__GFP_ZERO); 84 : : 85 : : /* 86 : : * We're using pages (not slab allocations) directly for kernel data 87 : : * structures, so we need to explicitly inform kmemleak of them in order 88 : : * to avoid false positive memory leak reports. 89 : : */ 90 : : kmemleak_alloc(node, PAGE_SIZE, 1, gfp_mask); 91 : : return node; 92 : : } 93 : : 94 : : static inline void genradix_free_node(struct genradix_node *node) 95 : : { 96 : : kmemleak_free(node); 97 : 0 : free_page((unsigned long)node); 98 : : } 99 : : 100 : : /* 101 : : * Returns pointer to the specified byte @offset within @radix, allocating it if 102 : : * necessary - newly allocated slots are always zeroed out: 103 : : */ 104 : 0 : void *__genradix_ptr_alloc(struct __genradix *radix, size_t offset, 105 : : gfp_t gfp_mask) 106 : : { 107 : 0 : struct genradix_root *v = READ_ONCE(radix->root); 108 : : struct genradix_node *n, *new_node = NULL; 109 : : unsigned level; 110 : : 111 : : /* Increase tree depth if necessary: */ 112 : : while (1) { 113 : : struct genradix_root *r = v, *new_root; 114 : : 115 : : n = genradix_root_to_node(r); 116 : : level = genradix_root_to_depth(r); 117 : : 118 : 0 : if (n && ilog2(offset) < genradix_depth_shift(level)) 119 : : break; 120 : : 121 : 0 : if (!new_node) { 122 : : new_node = genradix_alloc_node(gfp_mask); 123 : 0 : if (!new_node) 124 : : return NULL; 125 : : } 126 : : 127 : 0 : new_node->children[0] = n; 128 : 0 : new_root = ((struct genradix_root *) 129 : 0 : ((unsigned long) new_node | (n ? level + 1 : 0))); 130 : : 131 : 0 : if ((v = cmpxchg_release(&radix->root, r, new_root)) == r) { 132 : : v = new_root; 133 : : new_node = NULL; 134 : : } 135 : : } 136 : : 137 : 0 : while (level--) { 138 : 0 : struct genradix_node **p = 139 : 0 : &n->children[offset >> genradix_depth_shift(level)]; 140 : 0 : offset &= genradix_depth_size(level) - 1; 141 : : 142 : 0 : n = READ_ONCE(*p); 143 : 0 : if (!n) { 144 : 0 : if (!new_node) { 145 : : new_node = genradix_alloc_node(gfp_mask); 146 : 0 : if (!new_node) 147 : : return NULL; 148 : : } 149 : : 150 : 0 : if (!(n = cmpxchg_release(p, NULL, new_node))) 151 : : swap(n, new_node); 152 : : } 153 : : } 154 : : 155 : 0 : if (new_node) 156 : : genradix_free_node(new_node); 157 : : 158 : 0 : return &n->data[offset]; 159 : : } 160 : : EXPORT_SYMBOL(__genradix_ptr_alloc); 161 : : 162 : 0 : void *__genradix_iter_peek(struct genradix_iter *iter, 163 : : struct __genradix *radix, 164 : : size_t objs_per_page) 165 : : { 166 : : struct genradix_root *r; 167 : : struct genradix_node *n; 168 : : unsigned level, i; 169 : : restart: 170 : 0 : r = READ_ONCE(radix->root); 171 : 0 : if (!r) 172 : : return NULL; 173 : : 174 : : n = genradix_root_to_node(r); 175 : : level = genradix_root_to_depth(r); 176 : : 177 : 0 : if (ilog2(iter->offset) >= genradix_depth_shift(level)) 178 : : return NULL; 179 : : 180 : 0 : while (level) { 181 : 0 : level--; 182 : : 183 : 0 : i = (iter->offset >> genradix_depth_shift(level)) & 184 : : (GENRADIX_ARY - 1); 185 : : 186 : 0 : while (!n->children[i]) { 187 : 0 : i++; 188 : 0 : iter->offset = round_down(iter->offset + 189 : : genradix_depth_size(level), 190 : : genradix_depth_size(level)); 191 : 0 : iter->pos = (iter->offset >> PAGE_SHIFT) * 192 : : objs_per_page; 193 : 0 : if (i == GENRADIX_ARY) 194 : : goto restart; 195 : : } 196 : : 197 : 0 : n = n->children[i]; 198 : : } 199 : : 200 : 0 : return &n->data[iter->offset & (PAGE_SIZE - 1)]; 201 : : } 202 : : EXPORT_SYMBOL(__genradix_iter_peek); 203 : : 204 : 0 : static void genradix_free_recurse(struct genradix_node *n, unsigned level) 205 : : { 206 : 0 : if (level) { 207 : : unsigned i; 208 : : 209 : 0 : for (i = 0; i < GENRADIX_ARY; i++) 210 : 0 : if (n->children[i]) 211 : 0 : genradix_free_recurse(n->children[i], level - 1); 212 : : } 213 : : 214 : : genradix_free_node(n); 215 : 0 : } 216 : : 217 : 0 : int __genradix_prealloc(struct __genradix *radix, size_t size, 218 : : gfp_t gfp_mask) 219 : : { 220 : : size_t offset; 221 : : 222 : 0 : for (offset = 0; offset < size; offset += PAGE_SIZE) 223 : 0 : if (!__genradix_ptr_alloc(radix, offset, gfp_mask)) 224 : : return -ENOMEM; 225 : : 226 : : return 0; 227 : : } 228 : : EXPORT_SYMBOL(__genradix_prealloc); 229 : : 230 : 0 : void __genradix_free(struct __genradix *radix) 231 : : { 232 : 0 : struct genradix_root *r = xchg(&radix->root, NULL); 233 : : 234 : 0 : genradix_free_recurse(genradix_root_to_node(r), 235 : : genradix_root_to_depth(r)); 236 : 0 : } 237 : : EXPORT_SYMBOL(__genradix_free);