A new helper is introduced to calculate the memory usage of devmap and devmap_hash. The number of dynamically allocated elements are recored for devmap_hash already, but not for devmap. To track the memory size of dynamically allocated elements, this patch also count the numbers for devmap. The result as follows, - before 40: devmap name count_map flags 0x80 key 4B value 4B max_entries 65536 memlock 524288B 41: devmap_hash name count_map flags 0x80 key 4B value 4B max_entries 65536 memlock 524288B - after 40: devmap name count_map flags 0x80 <<<< no elements key 4B value 4B max_entries 65536 memlock 524608B 41: devmap_hash name count_map flags 0x80 <<<< no elements key 4B value 4B max_entries 65536 memlock 524608B Note that the number of buckets is same with max_entries for devmap_hash in this case.
Unified · Split
| @@ -819,8 +819,10 @@ static int dev_map_delete_elem(struct bpf_map *map, void *key) · 818 unmodified lines | |||
| 819 | return -EINVAL; | 819 | return -EINVAL; |
| 820 | 820 | ||
| 821 | old_dev = unrcu_pointer(xchg(&dtab->netdev_map[k], NULL)); | 821 | old_dev = unrcu_pointer(xchg(&dtab->netdev_map[k], NULL)); |
| 822 | if (old_dev) | 822 | if (old_dev) { |
| 823 | call_rcu(&old_dev->rcu, __dev_map_entry_free); | 823 | call_rcu(&old_dev->rcu, __dev_map_entry_free); |
| 824 | atomic_dec((atomic_t *)&dtab->items); | ||
| 825 | } | ||
| 824 | return 0; | 826 | return 0; |
| 825 | } | 827 | } |
| 826 | 828 | ||
| @@ -931,6 +933,8 @@ static int __dev_map_update_elem(struct net *net, struct bpf_map *map, · 104 unmodified lines | |||
| 931 | old_dev = unrcu_pointer(xchg(&dtab->netdev_map[i], RCU_INITIALIZER(dev))); | 933 | old_dev = unrcu_pointer(xchg(&dtab->netdev_map[i], RCU_INITIALIZER(dev))); |
| 932 | if (old_dev) | 934 | if (old_dev) |
| 933 | call_rcu(&old_dev->rcu, __dev_map_entry_free); | 935 | call_rcu(&old_dev->rcu, __dev_map_entry_free); |
| 936 | else | ||
| 937 | atomic_inc((atomic_t *)&dtab->items); | ||
| 934 | 938 | ||
| 935 | return 0; | 939 | return 0; |
| 936 | } | 940 | } |
| @@ -1016,6 +1020,20 @@ static int dev_hash_map_redirect(struct bpf_map *map, u64 ifindex, u64 flags) · 79 unmodified lines | |||
| 1016 | __dev_map_hash_lookup_elem); | 1020 | __dev_map_hash_lookup_elem); |
| 1017 | } | 1021 | } |
| 1018 | 1022 | ||
| 1023 | static u64 dev_map_mem_usage(const struct bpf_map *map) | ||
| 1024 | { | ||
| 1025 | struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); | ||
| 1026 | u64 usage = sizeof(struct bpf_dtab); | ||
| 1027 | |||
| 1028 | if (map->map_type == BPF_MAP_TYPE_DEVMAP_HASH) | ||
| 1029 | usage += (u64)dtab->n_buckets * sizeof(struct hlist_head); | ||
| 1030 | else | ||
| 1031 | usage += (u64)map->max_entries * sizeof(struct bpf_dtab_netdev *); | ||
| 1032 | usage += atomic_read((atomic_t *)&dtab->items) * | ||
| 1033 | (u64)sizeof(struct bpf_dtab_netdev); | ||
| 1034 | return usage; | ||
| 1035 | } | ||
| 1036 | |||
| 1019 | BTF_ID_LIST_SINGLE(dev_map_btf_ids, struct, bpf_dtab) | 1037 | BTF_ID_LIST_SINGLE(dev_map_btf_ids, struct, bpf_dtab) |
| 1020 | const struct bpf_map_ops dev_map_ops = { | 1038 | const struct bpf_map_ops dev_map_ops = { |
| 1021 | .map_meta_equal = bpf_map_meta_equal, | 1039 | .map_meta_equal = bpf_map_meta_equal, |
| @@ -1026,6 +1044,7 @@ const struct bpf_map_ops dev_map_ops = { · 4 unmodified lines | |||
| 1026 | .map_update_elem = dev_map_update_elem, | 1044 | .map_update_elem = dev_map_update_elem, |
| 1027 | .map_delete_elem = dev_map_delete_elem, | 1045 | .map_delete_elem = dev_map_delete_elem, |
| 1028 | .map_check_btf = map_check_no_btf, | 1046 | .map_check_btf = map_check_no_btf, |
| 1047 | .map_mem_usage = dev_map_mem_usage, | ||
| 1029 | .map_btf_id = &dev_map_btf_ids[0], | 1048 | .map_btf_id = &dev_map_btf_ids[0], |
| 1030 | .map_redirect = dev_map_redirect, | 1049 | .map_redirect = dev_map_redirect, |
| 1031 | }; | 1050 | }; |
| @@ -1039,6 +1058,7 @@ const struct bpf_map_ops dev_map_hash_ops = { · 7 unmodified lines | |||
| 1039 | .map_update_elem = dev_map_hash_update_elem, | 1058 | .map_update_elem = dev_map_hash_update_elem, |
| 1040 | .map_delete_elem = dev_map_hash_delete_elem, | 1059 | .map_delete_elem = dev_map_hash_delete_elem, |
| 1041 | .map_check_btf = map_check_no_btf, | 1060 | .map_check_btf = map_check_no_btf, |
| 1061 | .map_mem_usage = dev_map_mem_usage, | ||
| 1042 | .map_btf_id = &dev_map_btf_ids[0], | 1062 | .map_btf_id = &dev_map_btf_ids[0], |
| 1043 | .map_redirect = dev_hash_map_redirect, | 1063 | .map_redirect = dev_hash_map_redirect, |
| 1044 | }; | 1064 | }; |
| @@ -1109,9 +1129,11 @@ static int dev_map_notification(struct notifier_block *notifier, · 64 unmodified lines | |||
| 1109 | if (!dev || netdev != dev->dev) | 1129 | if (!dev || netdev != dev->dev) |
| 1110 | continue; | 1130 | continue; |
| 1111 | odev = unrcu_pointer(cmpxchg(&dtab->netdev_map[i], RCU_INITIALIZER(dev), NULL)); | 1131 | odev = unrcu_pointer(cmpxchg(&dtab->netdev_map[i], RCU_INITIALIZER(dev), NULL)); |
| 1112 | if (dev == odev) | 1132 | if (dev == odev) { |
| 1113 | call_rcu(&dev->rcu, | 1133 | call_rcu(&dev->rcu, |
| 1114 | __dev_map_entry_free); | 1134 | __dev_map_entry_free); |
| 1135 | atomic_dec((atomic_t *)&dtab->items); | ||
| 1136 | } | ||
| 1115 | } | 1137 | } |
| 1116 | } | 1138 | } |
| 1117 | rcu_read_unlock(); | 1139 | rcu_read_unlock(); |