aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/bpf/hashtab.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 3ea87fb19a94..63c86a7be2a1 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -45,8 +45,13 @@ enum extra_elem_state {
45struct htab_elem { 45struct htab_elem {
46 union { 46 union {
47 struct hlist_node hash_node; 47 struct hlist_node hash_node;
48 struct bpf_htab *htab; 48 struct {
49 struct pcpu_freelist_node fnode; 49 void *padding;
50 union {
51 struct bpf_htab *htab;
52 struct pcpu_freelist_node fnode;
53 };
54 };
50 }; 55 };
51 union { 56 union {
52 struct rcu_head rcu; 57 struct rcu_head rcu;
@@ -162,7 +167,8 @@ skip_percpu_elems:
162 offsetof(struct htab_elem, lru_node), 167 offsetof(struct htab_elem, lru_node),
163 htab->elem_size, htab->map.max_entries); 168 htab->elem_size, htab->map.max_entries);
164 else 169 else
165 pcpu_freelist_populate(&htab->freelist, htab->elems, 170 pcpu_freelist_populate(&htab->freelist,
171 htab->elems + offsetof(struct htab_elem, fnode),
166 htab->elem_size, htab->map.max_entries); 172 htab->elem_size, htab->map.max_entries);
167 173
168 return 0; 174 return 0;
@@ -217,6 +223,11 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
217 int err, i; 223 int err, i;
218 u64 cost; 224 u64 cost;
219 225
226 BUILD_BUG_ON(offsetof(struct htab_elem, htab) !=
227 offsetof(struct htab_elem, hash_node.pprev));
228 BUILD_BUG_ON(offsetof(struct htab_elem, fnode.next) !=
229 offsetof(struct htab_elem, hash_node.pprev));
230
220 if (lru && !capable(CAP_SYS_ADMIN)) 231 if (lru && !capable(CAP_SYS_ADMIN))
221 /* LRU implementation is much complicated than other 232 /* LRU implementation is much complicated than other
222 * maps. Hence, limit to CAP_SYS_ADMIN for now. 233 * maps. Hence, limit to CAP_SYS_ADMIN for now.
@@ -582,9 +593,13 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
582 int err = 0; 593 int err = 0;
583 594
584 if (prealloc) { 595 if (prealloc) {
585 l_new = (struct htab_elem *)pcpu_freelist_pop(&htab->freelist); 596 struct pcpu_freelist_node *l;
586 if (!l_new) 597
598 l = pcpu_freelist_pop(&htab->freelist);
599 if (!l)
587 err = -E2BIG; 600 err = -E2BIG;
601 else
602 l_new = container_of(l, struct htab_elem, fnode);
588 } else { 603 } else {
589 if (atomic_inc_return(&htab->count) > htab->map.max_entries) { 604 if (atomic_inc_return(&htab->count) > htab->map.max_entries) {
590 atomic_dec(&htab->count); 605 atomic_dec(&htab->count);