History

bpf: Allow RCU-protected lookups to happen from bh context

XDP programs are called from a NAPI poll context, which means the RCU reference liveness is ensured by local_bh_disable(). Add rcu_read_lock_bh_held() as a condition to the RCU checks for map lookups so lockdep understands that the dereferences are safe from inside *either* an rcu_read_lock() section *or* a local_bh_disable() section. While both bh_disabled and rcu_read_lock() provide RCU protection, they are semantically distinct, so we need both conditions to prevent lockdep complaints. This change is done in preparation for removing the redundant rcu_read_lock()s from drivers.

Toke Høiland-Jørgensen committed 5 years ago

Commit 694cea31 parent e74c74f3 files · +21 −12Browse files

Unified · Split

3 files
  1. kernel/bpf/hashtab.c +14 −7
  2. kernel/bpf/helpers.c +3 −3
  3. kernel/bpf/lpm_trie.c +4 −2
kernel/bpf/hashtab.c+14−7
@@ -596,7 +596,8 @@ static void *__htab_map_lookup_elem(struct bpf_map *map, void *key) · 595 unmodified lines
596596 struct htab_elem *l;
597597 u32 hash, key_size;
598598
599− WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
599+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
600+ !rcu_read_lock_bh_held());
600601
601602 key_size = map->key_size;
602603
@@ -989,7 +990,8 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value, · 386 unmodified lines
989990 /* unknown flags */
990991 return -EINVAL;
991992
992− WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
993+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
994+ !rcu_read_lock_bh_held());
993995
994996 key_size = map->key_size;
995997
@@ -1082,7 +1084,8 @@ static int htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value, · 86 unmodified lines
10821084 /* unknown flags */
10831085 return -EINVAL;
10841086
1085− WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
1087+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
1088+ !rcu_read_lock_bh_held());
10861089
10871090 key_size = map->key_size;
10881091
@@ -1148,7 +1151,8 @@ static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key, · 59 unmodified lines
11481151 /* unknown flags */
11491152 return -EINVAL;
11501153
1151− WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
1154+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
1155+ !rcu_read_lock_bh_held());
11521156
11531157 key_size = map->key_size;
11541158
@@ -1202,7 +1206,8 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key, · 47 unmodified lines
12021206 /* unknown flags */
12031207 return -EINVAL;
12041208
1205− WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
1209+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
1210+ !rcu_read_lock_bh_held());
12061211
12071212 key_size = map->key_size;
12081213
@@ -1276,7 +1281,8 @@ static int htab_map_delete_elem(struct bpf_map *map, void *key) · 67 unmodified lines
12761281 u32 hash, key_size;
12771282 int ret;
12781283
1279− WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
1284+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
1285+ !rcu_read_lock_bh_held());
12801286
12811287 key_size = map->key_size;
12821288
@@ -1311,7 +1317,8 @@ static int htab_lru_map_delete_elem(struct bpf_map *map, void *key) · 28 unmodified lines
13111317 u32 hash, key_size;
13121318 int ret;
13131319
1314− WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
1320+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held() &&
1321+ !rcu_read_lock_bh_held());
13151322
13161323 key_size = map->key_size;
13171324
kernel/bpf/helpers.c+3−3
@@ -29,7 +29,7 @@ · 28 unmodified lines
2929 */
3030 BPF_CALL_2(bpf_map_lookup_elem, struct bpf_map *, map, void *, key)
3131 {
32− WARN_ON_ONCE(!rcu_read_lock_held());
32+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
3333 return (unsigned long) map->ops->map_lookup_elem(map, key);
3434 }
3535
@@ -45,7 +45,7 @@ const struct bpf_func_proto bpf_map_lookup_elem_proto = { · 9 unmodified lines
4545 BPF_CALL_4(bpf_map_update_elem, struct bpf_map *, map, void *, key,
4646 void *, value, u64, flags)
4747 {
48− WARN_ON_ONCE(!rcu_read_lock_held());
48+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
4949 return map->ops->map_update_elem(map, key, value, flags);
5050 }
5151
@@ -62,7 +62,7 @@ const struct bpf_func_proto bpf_map_update_elem_proto = { · 10 unmodified lines
6262
6363 BPF_CALL_2(bpf_map_delete_elem, struct bpf_map *, map, void *, key)
6464 {
65− WARN_ON_ONCE(!rcu_read_lock_held());
65+ WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_bh_held());
6666 return map->ops->map_delete_elem(map, key);
6767 }
6868
kernel/bpf/lpm_trie.c+4−2
@@ -232,7 +232,8 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key) · 231 unmodified lines
232232
233233 /* Start walking the trie from the root node ... */
234234
235− for (node = rcu_dereference(trie->root); node;) {
235+ for (node = rcu_dereference_check(trie->root, rcu_read_lock_bh_held());
236+ node;) {
236237 unsigned int next_bit;
237238 size_t matchlen;
238239
@@ -264,7 +265,8 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key) · 25 unmodified lines
264265 * traverse down.
265266 */
266267 next_bit = extract_bit(key->data, node->prefixlen);
267− node = rcu_dereference(node->child[next_bit]);
268+ node = rcu_dereference_check(node->child[next_bit],
269+ rcu_read_lock_bh_held());
268270 }
269271
270272 if (!found)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t