[PATCH bpf-next 1/9] hashtab: Add new bpf_map_fd_put_value op

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Toke Høiland-Jørgensen <toke@xxxxxxxxxx>

The fd type maps all resolve the fd into a pointer to the underlying object
when it is inserted into the map, and stores that pointer as the real array
value. The htab code assumes that the map value is this single pointer, and
dereferences it before passing it to the map fd_put_ptr() op.

For xdp chain maps we want to be able to store multiple pointers, so we
need to get the pointer to the map value store, not the dereferenced
pointer to the actual object. So add a new more general
bpf_map_fd_put_value() op that takes the map value instead of the
dereferenced pointer, and use this on map element free.

Signed-off-by: Toke Høiland-Jørgensen <toke@xxxxxxxxxx>
---
 include/linux/bpf.h     |    1 +
 kernel/bpf/hashtab.c    |   16 ++++++----------
 kernel/bpf/map_in_map.c |    7 +++++++
 kernel/bpf/map_in_map.h |    1 +
 4 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 5b9d22338606..be3e9e9109c7 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -50,6 +50,7 @@ struct bpf_map_ops {
 	void *(*map_fd_get_ptr)(struct bpf_map *map, struct file *map_file,
 				int fd);
 	void (*map_fd_put_ptr)(void *ptr);
+	void (*map_fd_put_value)(void *value);
 	u32 (*map_gen_lookup)(struct bpf_map *map, struct bpf_insn *insn_buf);
 	u32 (*map_fd_sys_lookup_elem)(void *ptr);
 	void (*map_seq_show_elem)(struct bpf_map *map, void *key,
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 22066a62c8c9..113e1286e184 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -87,11 +87,6 @@ static inline void __percpu *htab_elem_get_ptr(struct htab_elem *l, u32 key_size
 	return *(void __percpu **)(l->key + key_size);
 }
 
-static void *fd_htab_map_get_ptr(const struct bpf_map *map, struct htab_elem *l)
-{
-	return *(void **)(l->key + roundup(map->key_size, 8));
-}
-
 static struct htab_elem *get_htab_elem(struct bpf_htab *htab, int i)
 {
 	return (struct htab_elem *) (htab->elems + i * htab->elem_size);
@@ -679,10 +674,10 @@ static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
 {
 	struct bpf_map *map = &htab->map;
 
-	if (map->ops->map_fd_put_ptr) {
-		void *ptr = fd_htab_map_get_ptr(map, l);
+	if (map->ops->map_fd_put_value) {
+		void *value = l->key + round_up(map->key_size, 8);
 
-		map->ops->map_fd_put_ptr(ptr);
+		map->ops->map_fd_put_value(value);
 	}
 
 	if (htab_is_prealloc(htab)) {
@@ -1400,9 +1395,9 @@ static void fd_htab_map_free(struct bpf_map *map)
 		head = select_bucket(htab, i);
 
 		hlist_nulls_for_each_entry_safe(l, n, head, hash_node) {
-			void *ptr = fd_htab_map_get_ptr(map, l);
+			void *value = l->key + round_up(map->key_size, 8);
 
-			map->ops->map_fd_put_ptr(ptr);
+			map->ops->map_fd_put_value(value);
 		}
 	}
 
@@ -1510,6 +1505,7 @@ const struct bpf_map_ops htab_of_maps_map_ops = {
 	.map_delete_elem = htab_map_delete_elem,
 	.map_fd_get_ptr = bpf_map_fd_get_ptr,
 	.map_fd_put_ptr = bpf_map_fd_put_ptr,
+	.map_fd_put_value = bpf_map_fd_put_value,
 	.map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem,
 	.map_gen_lookup = htab_of_map_gen_lookup,
 	.map_check_btf = map_check_no_btf,
diff --git a/kernel/bpf/map_in_map.c b/kernel/bpf/map_in_map.c
index fab4fb134547..1b4e8b6da777 100644
--- a/kernel/bpf/map_in_map.c
+++ b/kernel/bpf/map_in_map.c
@@ -114,6 +114,13 @@ void bpf_map_fd_put_ptr(void *ptr)
 	bpf_map_put(ptr);
 }
 
+void bpf_map_fd_put_value(void *value)
+{
+	void **ptr = value;
+
+	bpf_map_fd_put_ptr(*ptr);
+}
+
 u32 bpf_map_fd_sys_lookup_elem(void *ptr)
 {
 	return ((struct bpf_map *)ptr)->id;
diff --git a/kernel/bpf/map_in_map.h b/kernel/bpf/map_in_map.h
index a507bf6ef8b9..68d1a52e1757 100644
--- a/kernel/bpf/map_in_map.h
+++ b/kernel/bpf/map_in_map.h
@@ -16,6 +16,7 @@ bool bpf_map_meta_equal(const struct bpf_map *meta0,
 void *bpf_map_fd_get_ptr(struct bpf_map *map, struct file *map_file,
 			 int ufd);
 void bpf_map_fd_put_ptr(void *ptr);
+void bpf_map_fd_put_value(void *value);
 u32 bpf_map_fd_sys_lookup_elem(void *ptr);
 
 #endif




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux