0001
0002 #include <linux/export.h>
0003 #include <linux/generic-radix-tree.h>
0004 #include <linux/gfp.h>
0005 #include <linux/kmemleak.h>
0006
0007 #define GENRADIX_ARY (PAGE_SIZE / sizeof(struct genradix_node *))
0008 #define GENRADIX_ARY_SHIFT ilog2(GENRADIX_ARY)
0009
0010 struct genradix_node {
0011 union {
0012
0013 struct genradix_node *children[GENRADIX_ARY];
0014
0015
0016 u8 data[PAGE_SIZE];
0017 };
0018 };
0019
0020 static inline int genradix_depth_shift(unsigned depth)
0021 {
0022 return PAGE_SHIFT + GENRADIX_ARY_SHIFT * depth;
0023 }
0024
0025
0026
0027
0028 static inline size_t genradix_depth_size(unsigned depth)
0029 {
0030 return 1UL << genradix_depth_shift(depth);
0031 }
0032
0033
0034 #define GENRADIX_MAX_DEPTH \
0035 DIV_ROUND_UP(BITS_PER_LONG - PAGE_SHIFT, GENRADIX_ARY_SHIFT)
0036
0037 #define GENRADIX_DEPTH_MASK \
0038 ((unsigned long) (roundup_pow_of_two(GENRADIX_MAX_DEPTH + 1) - 1))
0039
0040 static inline unsigned genradix_root_to_depth(struct genradix_root *r)
0041 {
0042 return (unsigned long) r & GENRADIX_DEPTH_MASK;
0043 }
0044
0045 static inline struct genradix_node *genradix_root_to_node(struct genradix_root *r)
0046 {
0047 return (void *) ((unsigned long) r & ~GENRADIX_DEPTH_MASK);
0048 }
0049
0050
0051
0052
0053
0054 void *__genradix_ptr(struct __genradix *radix, size_t offset)
0055 {
0056 struct genradix_root *r = READ_ONCE(radix->root);
0057 struct genradix_node *n = genradix_root_to_node(r);
0058 unsigned level = genradix_root_to_depth(r);
0059
0060 if (ilog2(offset) >= genradix_depth_shift(level))
0061 return NULL;
0062
0063 while (1) {
0064 if (!n)
0065 return NULL;
0066 if (!level)
0067 break;
0068
0069 level--;
0070
0071 n = n->children[offset >> genradix_depth_shift(level)];
0072 offset &= genradix_depth_size(level) - 1;
0073 }
0074
0075 return &n->data[offset];
0076 }
0077 EXPORT_SYMBOL(__genradix_ptr);
0078
0079 static inline struct genradix_node *genradix_alloc_node(gfp_t gfp_mask)
0080 {
0081 struct genradix_node *node;
0082
0083 node = (struct genradix_node *)__get_free_page(gfp_mask|__GFP_ZERO);
0084
0085
0086
0087
0088
0089
0090 kmemleak_alloc(node, PAGE_SIZE, 1, gfp_mask);
0091 return node;
0092 }
0093
0094 static inline void genradix_free_node(struct genradix_node *node)
0095 {
0096 kmemleak_free(node);
0097 free_page((unsigned long)node);
0098 }
0099
0100
0101
0102
0103
0104 void *__genradix_ptr_alloc(struct __genradix *radix, size_t offset,
0105 gfp_t gfp_mask)
0106 {
0107 struct genradix_root *v = READ_ONCE(radix->root);
0108 struct genradix_node *n, *new_node = NULL;
0109 unsigned level;
0110
0111
0112 while (1) {
0113 struct genradix_root *r = v, *new_root;
0114
0115 n = genradix_root_to_node(r);
0116 level = genradix_root_to_depth(r);
0117
0118 if (n && ilog2(offset) < genradix_depth_shift(level))
0119 break;
0120
0121 if (!new_node) {
0122 new_node = genradix_alloc_node(gfp_mask);
0123 if (!new_node)
0124 return NULL;
0125 }
0126
0127 new_node->children[0] = n;
0128 new_root = ((struct genradix_root *)
0129 ((unsigned long) new_node | (n ? level + 1 : 0)));
0130
0131 if ((v = cmpxchg_release(&radix->root, r, new_root)) == r) {
0132 v = new_root;
0133 new_node = NULL;
0134 }
0135 }
0136
0137 while (level--) {
0138 struct genradix_node **p =
0139 &n->children[offset >> genradix_depth_shift(level)];
0140 offset &= genradix_depth_size(level) - 1;
0141
0142 n = READ_ONCE(*p);
0143 if (!n) {
0144 if (!new_node) {
0145 new_node = genradix_alloc_node(gfp_mask);
0146 if (!new_node)
0147 return NULL;
0148 }
0149
0150 if (!(n = cmpxchg_release(p, NULL, new_node)))
0151 swap(n, new_node);
0152 }
0153 }
0154
0155 if (new_node)
0156 genradix_free_node(new_node);
0157
0158 return &n->data[offset];
0159 }
0160 EXPORT_SYMBOL(__genradix_ptr_alloc);
0161
0162 void *__genradix_iter_peek(struct genradix_iter *iter,
0163 struct __genradix *radix,
0164 size_t objs_per_page)
0165 {
0166 struct genradix_root *r;
0167 struct genradix_node *n;
0168 unsigned level, i;
0169 restart:
0170 r = READ_ONCE(radix->root);
0171 if (!r)
0172 return NULL;
0173
0174 n = genradix_root_to_node(r);
0175 level = genradix_root_to_depth(r);
0176
0177 if (ilog2(iter->offset) >= genradix_depth_shift(level))
0178 return NULL;
0179
0180 while (level) {
0181 level--;
0182
0183 i = (iter->offset >> genradix_depth_shift(level)) &
0184 (GENRADIX_ARY - 1);
0185
0186 while (!n->children[i]) {
0187 i++;
0188 iter->offset = round_down(iter->offset +
0189 genradix_depth_size(level),
0190 genradix_depth_size(level));
0191 iter->pos = (iter->offset >> PAGE_SHIFT) *
0192 objs_per_page;
0193 if (i == GENRADIX_ARY)
0194 goto restart;
0195 }
0196
0197 n = n->children[i];
0198 }
0199
0200 return &n->data[iter->offset & (PAGE_SIZE - 1)];
0201 }
0202 EXPORT_SYMBOL(__genradix_iter_peek);
0203
0204 static void genradix_free_recurse(struct genradix_node *n, unsigned level)
0205 {
0206 if (level) {
0207 unsigned i;
0208
0209 for (i = 0; i < GENRADIX_ARY; i++)
0210 if (n->children[i])
0211 genradix_free_recurse(n->children[i], level - 1);
0212 }
0213
0214 genradix_free_node(n);
0215 }
0216
0217 int __genradix_prealloc(struct __genradix *radix, size_t size,
0218 gfp_t gfp_mask)
0219 {
0220 size_t offset;
0221
0222 for (offset = 0; offset < size; offset += PAGE_SIZE)
0223 if (!__genradix_ptr_alloc(radix, offset, gfp_mask))
0224 return -ENOMEM;
0225
0226 return 0;
0227 }
0228 EXPORT_SYMBOL(__genradix_prealloc);
0229
0230 void __genradix_free(struct __genradix *radix)
0231 {
0232 struct genradix_root *r = xchg(&radix->root, NULL);
0233
0234 genradix_free_recurse(genradix_root_to_node(r),
0235 genradix_root_to_depth(r));
0236 }
0237 EXPORT_SYMBOL(__genradix_free);