History

bpf: Use mutex lock pool for bpf trampolines

Adding mutex lock pool that replaces bpf trampolines mutex. For tracing_multi link coming in following changes we need to lock all the involved trampolines during the attachment. This could mean thousands of mutex locks, which is not convenient. As suggested by Andrii we can replace bpf trampolines mutex with mutex pool, where each trampoline is hash-ed to one of the locks from the pool. It's better to lock all the pool mutexes (32 at the moment) than thousands of them. There is 48 (MAX_LOCK_DEPTH) lock limit allowed to be simultaneously held by task, so we need to keep 32 mutexes (5 bits) in the pool, so when we lock them all in following changes the lockdep won't scream. Removing the mutex_is_locked in bpf_trampoline_put, because we removed the mutex from bpf_trampoline.

Jiri Olsa committed 5 months ago

Commit e6abd4c1 parent 2cd298c2 files · +53 −26Browse files

Showing the changes to kernel (1 of 2 files). Show all

Unified · Split

kernel/bpf/trampoline.c+53−24
@@ -30,6 +30,35 @@ static struct hlist_head trampoline_ip_table[TRAMPOLINE_TABLE_SIZE]; · 29 unmodified lines
30/* serializes access to trampoline tables */30/* serializes access to trampoline tables */
31static DEFINE_MUTEX(trampoline_mutex);31static DEFINE_MUTEX(trampoline_mutex);
32 32
33/*
34 * Keep 32 trampoline locks (5 bits) in the pool so trampoline_lock_all()
35 * stays below MAX_LOCK_DEPTH. Each pool slot has a distinct lockdep
36 * class because trampoline_lock_all() takes all pool mutexes at once;
37 * otherwise lockdep would report recursive locking on same-class mutexes.
38 */
39#define TRAMPOLINE_LOCKS_BITS 5
40#define TRAMPOLINE_LOCKS_TABLE_SIZE (1 << TRAMPOLINE_LOCKS_BITS)
41
42static struct {
43 struct mutex mutex;
44 struct lock_class_key key;
45} trampoline_locks[TRAMPOLINE_LOCKS_TABLE_SIZE];
46
47static struct mutex *select_trampoline_lock(struct bpf_trampoline *tr)
48{
49 return &trampoline_locks[hash_ptr(tr, TRAMPOLINE_LOCKS_BITS)].mutex;
50}
51
52static void trampoline_lock(struct bpf_trampoline *tr)
53{
54 mutex_lock(select_trampoline_lock(tr));
55}
56
57static void trampoline_unlock(struct bpf_trampoline *tr)
58{
59 mutex_unlock(select_trampoline_lock(tr));
60}
61
33#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS62#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
34static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex);63static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex);
35 64
@@ -69,9 +98,9 @@ static int bpf_tramp_ftrace_ops_func(struct ftrace_ops *ops, unsigned long ip, · 33 unmodified lines
69 98
70 if (cmd == FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF) {99 if (cmd == FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF) {
71 /* This is called inside register_ftrace_direct_multi(), so100 /* This is called inside register_ftrace_direct_multi(), so
72 * tr->mutex is already locked.101 * trampoline's mutex is already locked.
73 */102 */
74 lockdep_assert_held_once(&tr->mutex);103 lockdep_assert_held_once(select_trampoline_lock(tr));
75 104
76 /* Instead of updating the trampoline here, we propagate105 /* Instead of updating the trampoline here, we propagate
77 * -EAGAIN to register_ftrace_direct(). Then we can106 * -EAGAIN to register_ftrace_direct(). Then we can
@@ -91,7 +120,7 @@ static int bpf_tramp_ftrace_ops_func(struct ftrace_ops *ops, unsigned long ip, · 13 unmodified lines
91 }120 }
92 121
93 /* The normal locking order is122 /* The normal locking order is
94 * tr->mutex => direct_mutex (ftrace.c) => ftrace_lock (ftrace.c)123 * select_trampoline_lock(tr) => direct_mutex (ftrace.c) => ftrace_lock (ftrace.c)
95 *124 *
96 * The following two commands are called from125 * The following two commands are called from
97 *126 *
@@ -99,12 +128,12 @@ static int bpf_tramp_ftrace_ops_func(struct ftrace_ops *ops, unsigned long ip, · 1 unmodified line
99 * cleanup_direct_functions_after_ipmodify128 * cleanup_direct_functions_after_ipmodify
100 *129 *
101 * In both cases, direct_mutex is already locked. Use130 * In both cases, direct_mutex is already locked. Use
102 * mutex_trylock(&tr->mutex) to avoid deadlock in race condition131 * mutex_trylock(select_trampoline_lock(tr)) to avoid deadlock in race condition
103 * (something else is making changes to this same trampoline).132 * (something else holds the same pool lock).
104 */133 */
105 if (!mutex_trylock(&tr->mutex)) {134 if (!mutex_trylock(select_trampoline_lock(tr))) {
106 /* sleep 1 ms to make sure whatever holding tr->mutex makes135 /* sleep 1 ms to make sure whatever holding select_trampoline_lock(tr)
107 * some progress.136 * makes some progress.
108 */137 */
109 msleep(1);138 msleep(1);
110 return -EAGAIN;139 return -EAGAIN;
@@ -129,7 +158,7 @@ static int bpf_tramp_ftrace_ops_func(struct ftrace_ops *ops, unsigned long ip, · 18 unmodified lines
129 break;158 break;
130 }159 }
131 160
132 mutex_unlock(&tr->mutex);161 trampoline_unlock(tr);
133 return ret;162 return ret;
134}163}
135#endif164#endif
@@ -359,7 +388,6 @@ static struct bpf_trampoline *bpf_trampoline_lookup(u64 key, unsigned long ip) · 223 unmodified lines
359 head = &trampoline_ip_table[hash_64(tr->ip, TRAMPOLINE_HASH_BITS)];388 head = &trampoline_ip_table[hash_64(tr->ip, TRAMPOLINE_HASH_BITS)];
360 hlist_add_head(&tr->hlist_ip, head);389 hlist_add_head(&tr->hlist_ip, head);
361 refcount_set(&tr->refcnt, 1);390 refcount_set(&tr->refcnt, 1);
362 mutex_init(&tr->mutex);
363 for (i = 0; i < BPF_TRAMP_MAX; i++)391 for (i = 0; i < BPF_TRAMP_MAX; i++)
364 INIT_HLIST_HEAD(&tr->progs_hlist[i]);392 INIT_HLIST_HEAD(&tr->progs_hlist[i]);
365out:393out:
@@ -843,9 +871,9 @@ int bpf_trampoline_link_prog(struct bpf_tramp_link *link, · 477 unmodified lines
843{871{
844 int err;872 int err;
845 873
846 mutex_lock(&tr->mutex);874 trampoline_lock(tr);
847 err = __bpf_trampoline_link_prog(link, tr, tgt_prog);875 err = __bpf_trampoline_link_prog(link, tr, tgt_prog);
848 mutex_unlock(&tr->mutex);876 trampoline_unlock(tr);
849 return err;877 return err;
850}878}
851 879
@@ -886,9 +914,9 @@ int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, · 34 unmodified lines
886{914{
887 int err;915 int err;
888 916
889 mutex_lock(&tr->mutex);917 trampoline_lock(tr);
890 err = __bpf_trampoline_unlink_prog(link, tr, tgt_prog);918 err = __bpf_trampoline_unlink_prog(link, tr, tgt_prog);
891 mutex_unlock(&tr->mutex);919 trampoline_unlock(tr);
892 return err;920 return err;
893}921}
894 922
@@ -998,12 +1026,12 @@ int bpf_trampoline_link_cgroup_shim(struct bpf_prog *prog, · 103 unmodified lines
998 if (!tr)1026 if (!tr)
999 return -ENOMEM;1027 return -ENOMEM;
1000 1028
1001 mutex_lock(&tr->mutex);1029 trampoline_lock(tr);
1002 1030
1003 shim_link = cgroup_shim_find(tr, bpf_func);1031 shim_link = cgroup_shim_find(tr, bpf_func);
1004 if (shim_link && !IS_ERR(bpf_link_inc_not_zero(&shim_link->link.link))) {1032 if (shim_link && !IS_ERR(bpf_link_inc_not_zero(&shim_link->link.link))) {
1005 /* Reusing existing shim attached by the other program. */1033 /* Reusing existing shim attached by the other program. */
1006 mutex_unlock(&tr->mutex);1034 trampoline_unlock(tr);
1007 bpf_trampoline_put(tr); /* bpf_trampoline_get above */1035 bpf_trampoline_put(tr); /* bpf_trampoline_get above */
1008 return 0;1036 return 0;
1009 }1037 }
@@ -1023,16 +1051,16 @@ int bpf_trampoline_link_cgroup_shim(struct bpf_prog *prog, · 13 unmodified lines
1023 shim_link->trampoline = tr;1051 shim_link->trampoline = tr;
1024 /* note, we're still holding tr refcnt from above */1052 /* note, we're still holding tr refcnt from above */
1025 1053
1026 mutex_unlock(&tr->mutex);1054 trampoline_unlock(tr);
1027 1055
1028 return 0;1056 return 0;
1029err:1057err:
1030 mutex_unlock(&tr->mutex);1058 trampoline_unlock(tr);
1031 1059
1032 if (shim_link)1060 if (shim_link)
1033 bpf_link_put(&shim_link->link.link);1061 bpf_link_put(&shim_link->link.link);
1034 1062
1035 /* have to release tr while _not_ holding its mutex */1063 /* have to release tr while _not_ holding pool mutex for trampoline */
1036 bpf_trampoline_put(tr); /* bpf_trampoline_get above */1064 bpf_trampoline_put(tr); /* bpf_trampoline_get above */
1037 1065
1038 return err;1066 return err;
@@ -1053,9 +1081,9 @@ void bpf_trampoline_unlink_cgroup_shim(struct bpf_prog *prog) · 14 unmodified lines
1053 if (WARN_ON_ONCE(!tr))1081 if (WARN_ON_ONCE(!tr))
1054 return;1082 return;
1055 1083
1056 mutex_lock(&tr->mutex);1084 trampoline_lock(tr);
1057 shim_link = cgroup_shim_find(tr, bpf_func);1085 shim_link = cgroup_shim_find(tr, bpf_func);
1058 mutex_unlock(&tr->mutex);1086 trampoline_unlock(tr);
1059 1087
1060 if (shim_link)1088 if (shim_link)
1061 bpf_link_put(&shim_link->link.link);1089 bpf_link_put(&shim_link->link.link);
@@ -1073,14 +1101,14 @@ struct bpf_trampoline *bpf_trampoline_get(u64 key, · 11 unmodified lines
1073 if (!tr)1101 if (!tr)
1074 return NULL;1102 return NULL;
1075 1103
1076 mutex_lock(&tr->mutex);1104 trampoline_lock(tr);
1077 if (tr->func.addr)1105 if (tr->func.addr)
1078 goto out;1106 goto out;
1079 1107
1080 memcpy(&tr->func.model, &tgt_info->fmodel, sizeof(tgt_info->fmodel));1108 memcpy(&tr->func.model, &tgt_info->fmodel, sizeof(tgt_info->fmodel));
1081 tr->func.addr = (void *)tgt_info->tgt_addr;1109 tr->func.addr = (void *)tgt_info->tgt_addr;
1082out:1110out:
1083 mutex_unlock(&tr->mutex);1111 trampoline_unlock(tr);
1084 return tr;1112 return tr;
1085}1113}
1086 1114
@@ -1093,7 +1121,6 @@ void bpf_trampoline_put(struct bpf_trampoline *tr) · 6 unmodified lines
1093 mutex_lock(&trampoline_mutex);1121 mutex_lock(&trampoline_mutex);
1094 if (!refcount_dec_and_test(&tr->refcnt))1122 if (!refcount_dec_and_test(&tr->refcnt))
1095 goto out;1123 goto out;
1096 WARN_ON_ONCE(mutex_is_locked(&tr->mutex));
1097 1124
1098 for (i = 0; i < BPF_TRAMP_MAX; i++)1125 for (i = 0; i < BPF_TRAMP_MAX; i++)
1099 if (WARN_ON_ONCE(!hlist_empty(&tr->progs_hlist[i])))1126 if (WARN_ON_ONCE(!hlist_empty(&tr->progs_hlist[i])))
@@ -1379,6 +1406,8 @@ static int __init init_trampolines(void) · 279 unmodified lines
1379 INIT_HLIST_HEAD(&trampoline_key_table[i]);1406 INIT_HLIST_HEAD(&trampoline_key_table[i]);
1380 for (i = 0; i < TRAMPOLINE_TABLE_SIZE; i++)1407 for (i = 0; i < TRAMPOLINE_TABLE_SIZE; i++)
1381 INIT_HLIST_HEAD(&trampoline_ip_table[i]);1408 INIT_HLIST_HEAD(&trampoline_ip_table[i]);
1409 for (i = 0; i < TRAMPOLINE_LOCKS_TABLE_SIZE; i++)
1410 __mutex_init(&trampoline_locks[i].mutex, "trampoline_lock", &trampoline_locks[i].key);
1382 return 0;1411 return 0;
1383}1412}
1384late_initcall(init_trampolines);1413late_initcall(init_trampolines);