|
@@ -82,6 +82,14 @@ static void bpf_map_free_deferred(struct work_struct *work)
|
|
map->ops->map_free(map);
|
|
map->ops->map_free(map);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void bpf_map_put_uref(struct bpf_map *map)
|
|
|
|
+{
|
|
|
|
+ if (atomic_dec_and_test(&map->usercnt)) {
|
|
|
|
+ if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY)
|
|
|
|
+ bpf_fd_array_map_clear(map);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/* decrement map refcnt and schedule it for freeing via workqueue
|
|
/* decrement map refcnt and schedule it for freeing via workqueue
|
|
* (unrelying map implementation ops->map_free() might sleep)
|
|
* (unrelying map implementation ops->map_free() might sleep)
|
|
*/
|
|
*/
|
|
@@ -93,17 +101,15 @@ void bpf_map_put(struct bpf_map *map)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static int bpf_map_release(struct inode *inode, struct file *filp)
|
|
|
|
|
|
+void bpf_map_put_with_uref(struct bpf_map *map)
|
|
{
|
|
{
|
|
- struct bpf_map *map = filp->private_data;
|
|
|
|
-
|
|
|
|
- if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY)
|
|
|
|
- /* prog_array stores refcnt-ed bpf_prog pointers
|
|
|
|
- * release them all when user space closes prog_array_fd
|
|
|
|
- */
|
|
|
|
- bpf_fd_array_map_clear(map);
|
|
|
|
-
|
|
|
|
|
|
+ bpf_map_put_uref(map);
|
|
bpf_map_put(map);
|
|
bpf_map_put(map);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int bpf_map_release(struct inode *inode, struct file *filp)
|
|
|
|
+{
|
|
|
|
+ bpf_map_put_with_uref(filp->private_data);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -142,6 +148,7 @@ static int map_create(union bpf_attr *attr)
|
|
return PTR_ERR(map);
|
|
return PTR_ERR(map);
|
|
|
|
|
|
atomic_set(&map->refcnt, 1);
|
|
atomic_set(&map->refcnt, 1);
|
|
|
|
+ atomic_set(&map->usercnt, 1);
|
|
|
|
|
|
err = bpf_map_charge_memlock(map);
|
|
err = bpf_map_charge_memlock(map);
|
|
if (err)
|
|
if (err)
|
|
@@ -174,7 +181,14 @@ struct bpf_map *__bpf_map_get(struct fd f)
|
|
return f.file->private_data;
|
|
return f.file->private_data;
|
|
}
|
|
}
|
|
|
|
|
|
-struct bpf_map *bpf_map_get(u32 ufd)
|
|
|
|
|
|
+void bpf_map_inc(struct bpf_map *map, bool uref)
|
|
|
|
+{
|
|
|
|
+ atomic_inc(&map->refcnt);
|
|
|
|
+ if (uref)
|
|
|
|
+ atomic_inc(&map->usercnt);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct bpf_map *bpf_map_get_with_uref(u32 ufd)
|
|
{
|
|
{
|
|
struct fd f = fdget(ufd);
|
|
struct fd f = fdget(ufd);
|
|
struct bpf_map *map;
|
|
struct bpf_map *map;
|
|
@@ -183,7 +197,7 @@ struct bpf_map *bpf_map_get(u32 ufd)
|
|
if (IS_ERR(map))
|
|
if (IS_ERR(map))
|
|
return map;
|
|
return map;
|
|
|
|
|
|
- atomic_inc(&map->refcnt);
|
|
|
|
|
|
+ bpf_map_inc(map, true);
|
|
fdput(f);
|
|
fdput(f);
|
|
|
|
|
|
return map;
|
|
return map;
|