Skip to content

Commit 2a01c7e

Browse files
committed
fix
1 parent eb3b128 commit 2a01c7e

File tree

2 files changed

+36
-42
lines changed

2 files changed

+36
-42
lines changed

kernel/bpf/trampoline.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ static int direct_ops_get(struct bpf_trampoline *tr)
176176
tr->fops = &direct_ops;
177177
return 0;
178178
}
179-
static void direct_ops_clear(struct bpf_trampoline *tr) { }
180179
static void direct_ops_free(struct bpf_trampoline *tr) { }
181180
#else
182181
static int direct_ops_get(struct bpf_trampoline *tr)
@@ -189,12 +188,6 @@ static int direct_ops_get(struct bpf_trampoline *tr)
189188
return 0;
190189
}
191190

192-
static void direct_ops_clear(struct bpf_trampoline *tr)
193-
{
194-
tr->fops->func = NULL;
195-
tr->fops->trampoline = 0;
196-
}
197-
198191
static void direct_ops_free(struct bpf_trampoline *tr)
199192
{
200193
if (tr->fops) {
@@ -548,9 +541,6 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
548541
* BPF_TRAMP_F_SHARE_IPMODIFY is set, we can generate the
549542
* trampoline again, and retry register.
550543
*/
551-
/* reset fops->func and fops->trampoline for re-register */
552-
direct_ops_clear(tr);
553-
554544
/* free im memory and reallocate later */
555545
bpf_tramp_image_free(im);
556546
goto again;

kernel/trace/ftrace.c

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6121,21 +6121,10 @@ static struct ftrace_hash *hash_add(struct ftrace_hash *a, struct ftrace_hash *b
61216121
return NULL;
61226122
}
61236123

6124-
static void reset_direct_hash(struct ftrace_ops *ops, struct ftrace_hash **hashp)
6125-
{
6126-
struct ftrace_hash *free_hash = direct_functions;
6127-
6128-
rcu_assign_pointer(direct_functions, *hashp);
6129-
*hashp = free_hash;
6130-
6131-
/* cleanup for possible another register call */
6132-
ops->func = NULL;
6133-
ops->trampoline = 0;
6134-
}
6135-
61366124
int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash)
61376125
{
6138-
struct ftrace_hash *filter_hash = NULL, *new_hash = NULL, *free_hash = NULL;
6126+
struct ftrace_hash *old_direct_functions = NULL, *new_direct_functions = NULL;
6127+
struct ftrace_hash *old_filter_hash = NULL, *new_filter_hash = NULL;
61396128
struct ftrace_func_entry *entry;
61406129
int i, size, err = -EINVAL;
61416130
bool reg;
@@ -6154,10 +6143,11 @@ int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash)
61546143
}
61556144
}
61566145

6157-
filter_hash = ops->func_hash ? ops->func_hash->filter_hash : NULL;
6146+
old_filter_hash = ops->func_hash ? ops->func_hash->filter_hash : NULL;
6147+
old_direct_functions = direct_functions;
61586148

61596149
/* If there's nothing in filter_hash we need to register the ops. */
6160-
reg = hash_count(filter_hash) == 0;
6150+
reg = hash_count(old_filter_hash) == 0;
61616151
if (reg) {
61626152
if (ops->func || ops->trampoline)
61636153
goto out_unlock;
@@ -6166,40 +6156,54 @@ int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash)
61666156
}
61676157

61686158
err = -ENOMEM;
6169-
filter_hash = hash_add(filter_hash, hash);
6170-
if (!filter_hash)
6159+
new_filter_hash = hash_add(old_filter_hash, hash);
6160+
if (!new_filter_hash)
61716161
goto out_unlock;
61726162

6173-
new_hash = hash_add(direct_functions, hash);
6174-
if (!new_hash)
6163+
new_direct_functions = hash_add(old_direct_functions, hash);
6164+
if (!new_direct_functions)
61756165
goto out_unlock;
61766166

6177-
free_hash = direct_functions;
6178-
rcu_assign_pointer(direct_functions, new_hash);
6167+
rcu_assign_pointer(direct_functions, new_direct_functions);
61796168

61806169
if (reg) {
61816170
ops->func = call_direct_funcs;
6182-
ops->flags = MULTI_FLAGS;
6171+
ops->flags |= MULTI_FLAGS;
61836172
ops->trampoline = FTRACE_REGS_ADDR;
6184-
ops->local_hash.filter_hash = filter_hash;
6173+
ops->local_hash.filter_hash = new_filter_hash;
61856174

61866175
err = register_ftrace_function_nolock(ops);
6187-
if (!err)
6188-
filter_hash = NULL;
6176+
if (err) {
6177+
/* restore old filter on error */
6178+
ops->local_hash.filter_hash = old_filter_hash;
6179+
old_filter_hash = new_filter_hash;
6180+
6181+
/* cleanup for possible another register call */
6182+
ops->func = NULL;
6183+
ops->trampoline = 0;
6184+
}
61896185
} else {
6190-
err = ftrace_update_ops(ops, filter_hash, EMPTY_HASH);
6186+
err = ftrace_update_ops(ops, new_filter_hash, EMPTY_HASH);
6187+
/*
6188+
* new_filter_hash is dup-ed, so we need to release it anyway,
6189+
* old_filter_hash either stays on error or is released already
6190+
*/
6191+
old_filter_hash = new_filter_hash;
61916192
}
61926193

6193-
if (err)
6194-
reset_direct_hash(ops, &free_hash);
6194+
if (err) {
6195+
/* reset direct_functions and free the new one */
6196+
rcu_assign_pointer(direct_functions, old_direct_functions);
6197+
old_direct_functions = new_direct_functions;
6198+
}
61956199

61966200
out_unlock:
61976201
mutex_unlock(&direct_mutex);
61986202

6199-
if (free_hash && free_hash != EMPTY_HASH)
6200-
call_rcu_tasks(&free_hash->rcu, register_ftrace_direct_cb);
6201-
if (filter_hash)
6202-
free_ftrace_hash(filter_hash);
6203+
if (old_direct_functions && old_direct_functions != EMPTY_HASH)
6204+
call_rcu_tasks(&old_direct_functions->rcu, register_ftrace_direct_cb);
6205+
if (old_filter_hash)
6206+
free_ftrace_hash(old_filter_hash);
62036207

62046208
return err;
62056209
}

0 commit comments

Comments
 (0)