|
@@ -73,11 +73,11 @@ static int array_map_alloc_check(union bpf_attr *attr)
|
|
|
static struct bpf_map *array_map_alloc(union bpf_attr *attr)
|
|
|
{
|
|
|
bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_ARRAY;
|
|
|
- int numa_node = bpf_map_attr_numa_node(attr);
|
|
|
+ int ret, numa_node = bpf_map_attr_numa_node(attr);
|
|
|
u32 elem_size, index_mask, max_entries;
|
|
|
bool unpriv = !capable(CAP_SYS_ADMIN);
|
|
|
+ u64 cost, array_size, mask64;
|
|
|
struct bpf_array *array;
|
|
|
- u64 array_size, mask64;
|
|
|
|
|
|
elem_size = round_up(attr->value_size, 8);
|
|
|
|
|
@@ -109,8 +109,19 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
|
|
|
array_size += (u64) max_entries * elem_size;
|
|
|
|
|
|
/* make sure there is no u32 overflow later in round_up() */
|
|
|
- if (array_size >= U32_MAX - PAGE_SIZE)
|
|
|
+ cost = array_size;
|
|
|
+ if (cost >= U32_MAX - PAGE_SIZE)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
+ if (percpu) {
|
|
|
+ cost += (u64)attr->max_entries * elem_size * num_possible_cpus();
|
|
|
+ if (cost >= U32_MAX - PAGE_SIZE)
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+ }
|
|
|
+ cost = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT;
|
|
|
+
|
|
|
+ ret = bpf_map_precharge_memlock(cost);
|
|
|
+ if (ret < 0)
|
|
|
+ return ERR_PTR(ret);
|
|
|
|
|
|
/* allocate all map elements and zero-initialize them */
|
|
|
array = bpf_map_area_alloc(array_size, numa_node);
|
|
@@ -121,20 +132,13 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
|
|
|
|
|
|
/* copy mandatory map attributes */
|
|
|
bpf_map_init_from_attr(&array->map, attr);
|
|
|
+ array->map.pages = cost;
|
|
|
array->elem_size = elem_size;
|
|
|
|
|
|
- if (!percpu)
|
|
|
- goto out;
|
|
|
-
|
|
|
- array_size += (u64) attr->max_entries * elem_size * num_possible_cpus();
|
|
|
-
|
|
|
- if (array_size >= U32_MAX - PAGE_SIZE ||
|
|
|
- bpf_array_alloc_percpu(array)) {
|
|
|
+ if (percpu && bpf_array_alloc_percpu(array)) {
|
|
|
bpf_map_area_free(array);
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
}
|
|
|
-out:
|
|
|
- array->map.pages = round_up(array_size, PAGE_SIZE) >> PAGE_SHIFT;
|
|
|
|
|
|
return &array->map;
|
|
|
}
|