diff options
Diffstat (limited to 'kernel/bpf/arraymap.c')
| -rw-r--r-- | kernel/bpf/arraymap.c | 56 | 
1 files changed, 35 insertions, 21 deletions
| diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 5e00b2333c26..d771a3872500 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -86,6 +86,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)  	array->map.key_size = attr->key_size;  	array->map.value_size = attr->value_size;  	array->map.max_entries = attr->max_entries; +	array->map.map_flags = attr->map_flags;  	array->elem_size = elem_size;  	if (!percpu) @@ -334,6 +335,26 @@ static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)  }  /* only called from syscall */ +int bpf_fd_array_map_lookup_elem(struct bpf_map *map, void *key, u32 *value) +{ +	void **elem, *ptr; +	int ret =  0; + +	if (!map->ops->map_fd_sys_lookup_elem) +		return -ENOTSUPP; + +	rcu_read_lock(); +	elem = array_map_lookup_elem(map, key); +	if (elem && (ptr = READ_ONCE(*elem))) +		*value = map->ops->map_fd_sys_lookup_elem(ptr); +	else +		ret = -ENOENT; +	rcu_read_unlock(); + +	return ret; +} + +/* only called from syscall */  int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file,  				 void *key, void *value, u64 map_flags)  { @@ -399,6 +420,11 @@ static void prog_fd_array_put_ptr(void *ptr)  	bpf_prog_put(ptr);  } +static u32 prog_fd_array_sys_lookup_elem(void *ptr) +{ +	return ((struct bpf_prog *)ptr)->aux->id; +} +  /* decrement refcnt of all bpf_progs that are stored in this map */  void bpf_fd_array_map_clear(struct bpf_map *map)  { @@ -417,6 +443,7 @@ const struct bpf_map_ops prog_array_map_ops = {  	.map_delete_elem = fd_array_map_delete_elem,  	.map_fd_get_ptr = prog_fd_array_get_ptr,  	.map_fd_put_ptr = prog_fd_array_put_ptr, +	.map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem,  };  static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file, @@ -451,38 +478,24 @@ static void bpf_event_entry_free_rcu(struct bpf_event_entry *ee)  static void *perf_event_fd_array_get_ptr(struct bpf_map *map,  					 struct file *map_file, int fd)  { -	const struct perf_event_attr *attr;  	struct bpf_event_entry *ee;  	struct perf_event *event;  	struct file *perf_file; +	u64 value;  	perf_file = perf_event_get(fd);  	if (IS_ERR(perf_file))  		return perf_file; +	ee = ERR_PTR(-EOPNOTSUPP);  	event = perf_file->private_data; -	ee = ERR_PTR(-EINVAL); - -	attr = perf_event_attrs(event); -	if (IS_ERR(attr) || attr->inherit) +	if (perf_event_read_local(event, &value) == -EOPNOTSUPP)  		goto err_out; -	switch (attr->type) { -	case PERF_TYPE_SOFTWARE: -		if (attr->config != PERF_COUNT_SW_BPF_OUTPUT) -			goto err_out; -		/* fall-through */ -	case PERF_TYPE_RAW: -	case PERF_TYPE_HARDWARE: -		ee = bpf_event_entry_gen(perf_file, map_file); -		if (ee) -			return ee; -		ee = ERR_PTR(-ENOMEM); -		/* fall-through */ -	default: -		break; -	} - +	ee = bpf_event_entry_gen(perf_file, map_file); +	if (ee) +		return ee; +	ee = ERR_PTR(-ENOMEM);  err_out:  	fput(perf_file);  	return ee; @@ -598,4 +611,5 @@ const struct bpf_map_ops array_of_maps_map_ops = {  	.map_delete_elem = fd_array_map_delete_elem,  	.map_fd_get_ptr = bpf_map_fd_get_ptr,  	.map_fd_put_ptr = bpf_map_fd_put_ptr, +	.map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem,  }; |