diff options
author | David S. Miller <davem@davemloft.net> | 2015-12-03 21:03:21 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-12-03 21:09:12 -0500 |
commit | f188b951f33a0464338f94f928338f84fc0e4392 (patch) | |
tree | 17ad63719242b1de0266627a1dc92ba869a3ba4e /kernel/bpf/syscall.c | |
parent | 6b20da4d8f3f6a3be9f67e3207f435cfaa5f7f97 (diff) | |
parent | 071f5d105a0ae93aeb02197c4ee3557e8cc57a21 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
drivers/net/ethernet/renesas/ravb_main.c
kernel/bpf/syscall.c
net/ipv4/ipmr.c
All three conflicts were cases of overlapping changes.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 6d1407bc1531..637397059f76 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -82,6 +82,14 @@ static void bpf_map_free_deferred(struct work_struct *work) | |||
82 | map->ops->map_free(map); | 82 | map->ops->map_free(map); |
83 | } | 83 | } |
84 | 84 | ||
85 | static void bpf_map_put_uref(struct bpf_map *map) | ||
86 | { | ||
87 | if (atomic_dec_and_test(&map->usercnt)) { | ||
88 | if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) | ||
89 | bpf_fd_array_map_clear(map); | ||
90 | } | ||
91 | } | ||
92 | |||
85 | /* decrement map refcnt and schedule it for freeing via workqueue | 93 | /* decrement map refcnt and schedule it for freeing via workqueue |
86 | * (unrelying map implementation ops->map_free() might sleep) | 94 | * (unrelying map implementation ops->map_free() might sleep) |
87 | */ | 95 | */ |
@@ -93,6 +101,18 @@ void bpf_map_put(struct bpf_map *map) | |||
93 | } | 101 | } |
94 | } | 102 | } |
95 | 103 | ||
104 | void bpf_map_put_with_uref(struct bpf_map *map) | ||
105 | { | ||
106 | bpf_map_put_uref(map); | ||
107 | bpf_map_put(map); | ||
108 | } | ||
109 | |||
110 | static int bpf_map_release(struct inode *inode, struct file *filp) | ||
111 | { | ||
112 | bpf_map_put_with_uref(filp->private_data); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
96 | #ifdef CONFIG_PROC_FS | 116 | #ifdef CONFIG_PROC_FS |
97 | static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp) | 117 | static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp) |
98 | { | 118 | { |
@@ -110,20 +130,6 @@ static void bpf_map_show_fdinfo(struct seq_file *m, struct file *filp) | |||
110 | } | 130 | } |
111 | #endif | 131 | #endif |
112 | 132 | ||
113 | static int bpf_map_release(struct inode *inode, struct file *filp) | ||
114 | { | ||
115 | struct bpf_map *map = filp->private_data; | ||
116 | |||
117 | if (map->map_type == BPF_MAP_TYPE_PROG_ARRAY) | ||
118 | /* prog_array stores refcnt-ed bpf_prog pointers | ||
119 | * release them all when user space closes prog_array_fd | ||
120 | */ | ||
121 | bpf_fd_array_map_clear(map); | ||
122 | |||
123 | bpf_map_put(map); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static const struct file_operations bpf_map_fops = { | 133 | static const struct file_operations bpf_map_fops = { |
128 | #ifdef CONFIG_PROC_FS | 134 | #ifdef CONFIG_PROC_FS |
129 | .show_fdinfo = bpf_map_show_fdinfo, | 135 | .show_fdinfo = bpf_map_show_fdinfo, |
@@ -162,6 +168,7 @@ static int map_create(union bpf_attr *attr) | |||
162 | return PTR_ERR(map); | 168 | return PTR_ERR(map); |
163 | 169 | ||
164 | atomic_set(&map->refcnt, 1); | 170 | atomic_set(&map->refcnt, 1); |
171 | atomic_set(&map->usercnt, 1); | ||
165 | 172 | ||
166 | err = bpf_map_charge_memlock(map); | 173 | err = bpf_map_charge_memlock(map); |
167 | if (err) | 174 | if (err) |
@@ -194,7 +201,14 @@ struct bpf_map *__bpf_map_get(struct fd f) | |||
194 | return f.file->private_data; | 201 | return f.file->private_data; |
195 | } | 202 | } |
196 | 203 | ||
197 | struct bpf_map *bpf_map_get(u32 ufd) | 204 | void bpf_map_inc(struct bpf_map *map, bool uref) |
205 | { | ||
206 | atomic_inc(&map->refcnt); | ||
207 | if (uref) | ||
208 | atomic_inc(&map->usercnt); | ||
209 | } | ||
210 | |||
211 | struct bpf_map *bpf_map_get_with_uref(u32 ufd) | ||
198 | { | 212 | { |
199 | struct fd f = fdget(ufd); | 213 | struct fd f = fdget(ufd); |
200 | struct bpf_map *map; | 214 | struct bpf_map *map; |
@@ -203,7 +217,7 @@ struct bpf_map *bpf_map_get(u32 ufd) | |||
203 | if (IS_ERR(map)) | 217 | if (IS_ERR(map)) |
204 | return map; | 218 | return map; |
205 | 219 | ||
206 | atomic_inc(&map->refcnt); | 220 | bpf_map_inc(map, true); |
207 | fdput(f); | 221 | fdput(f); |
208 | 222 | ||
209 | return map; | 223 | return map; |
@@ -246,7 +260,7 @@ static int map_lookup_elem(union bpf_attr *attr) | |||
246 | goto free_key; | 260 | goto free_key; |
247 | 261 | ||
248 | err = -ENOMEM; | 262 | err = -ENOMEM; |
249 | value = kmalloc(map->value_size, GFP_USER); | 263 | value = kmalloc(map->value_size, GFP_USER | __GFP_NOWARN); |
250 | if (!value) | 264 | if (!value) |
251 | goto free_key; | 265 | goto free_key; |
252 | 266 | ||
@@ -305,7 +319,7 @@ static int map_update_elem(union bpf_attr *attr) | |||
305 | goto free_key; | 319 | goto free_key; |
306 | 320 | ||
307 | err = -ENOMEM; | 321 | err = -ENOMEM; |
308 | value = kmalloc(map->value_size, GFP_USER); | 322 | value = kmalloc(map->value_size, GFP_USER | __GFP_NOWARN); |
309 | if (!value) | 323 | if (!value) |
310 | goto free_key; | 324 | goto free_key; |
311 | 325 | ||