mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
ftrace: Add modify_ftrace_direct_multi_nolock
This is similar to modify_ftrace_direct_multi, but does not acquire direct_mutex. This is useful when direct_mutex is already locked by the user. Signed-off-by: Song Liu <song@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org> Link: https://lore.kernel.org/bpf/20220720002126.803253-2-song@kernel.org
This commit is contained in:
parent
f664f9c6b4
commit
f96f644ab9
@ -340,6 +340,7 @@ unsigned long ftrace_find_rec_direct(unsigned long ip);
|
||||
int register_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr);
|
||||
int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr);
|
||||
int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr);
|
||||
int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsigned long addr);
|
||||
|
||||
#else
|
||||
struct ftrace_ops;
|
||||
@ -384,6 +385,10 @@ static inline int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned lo
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsigned long addr)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
|
||||
|
||||
#ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
|
||||
|
@ -5691,22 +5691,8 @@ int unregister_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(unregister_ftrace_direct_multi);
|
||||
|
||||
/**
|
||||
* modify_ftrace_direct_multi - Modify an existing direct 'multi' call
|
||||
* to call something else
|
||||
* @ops: The address of the struct ftrace_ops object
|
||||
* @addr: The address of the new trampoline to call at @ops functions
|
||||
*
|
||||
* This is used to unregister currently registered direct caller and
|
||||
* register new one @addr on functions registered in @ops object.
|
||||
*
|
||||
* Note there's window between ftrace_shutdown and ftrace_startup calls
|
||||
* where there will be no callbacks called.
|
||||
*
|
||||
* Returns: zero on success. Non zero on error, which includes:
|
||||
* -EINVAL - The @ops object was not properly registered.
|
||||
*/
|
||||
int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
|
||||
static int
|
||||
__modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
|
||||
{
|
||||
struct ftrace_hash *hash;
|
||||
struct ftrace_func_entry *entry, *iter;
|
||||
@ -5717,12 +5703,7 @@ int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
|
||||
int i, size;
|
||||
int err;
|
||||
|
||||
if (check_direct_multi(ops))
|
||||
return -EINVAL;
|
||||
if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&direct_mutex);
|
||||
lockdep_assert_held_once(&direct_mutex);
|
||||
|
||||
/* Enable the tmp_ops to have the same functions as the direct ops */
|
||||
ftrace_ops_init(&tmp_ops);
|
||||
@ -5730,7 +5711,7 @@ int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
|
||||
|
||||
err = register_ftrace_function(&tmp_ops);
|
||||
if (err)
|
||||
goto out_direct;
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Now the ftrace_ops_list_func() is called to do the direct callers.
|
||||
@ -5754,7 +5735,64 @@ int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
|
||||
/* Removing the tmp_ops will add the updated direct callers to the functions */
|
||||
unregister_ftrace_function(&tmp_ops);
|
||||
|
||||
out_direct:
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* modify_ftrace_direct_multi_nolock - Modify an existing direct 'multi' call
|
||||
* to call something else
|
||||
* @ops: The address of the struct ftrace_ops object
|
||||
* @addr: The address of the new trampoline to call at @ops functions
|
||||
*
|
||||
* This is used to unregister currently registered direct caller and
|
||||
* register new one @addr on functions registered in @ops object.
|
||||
*
|
||||
* Note there's window between ftrace_shutdown and ftrace_startup calls
|
||||
* where there will be no callbacks called.
|
||||
*
|
||||
* Caller should already have direct_mutex locked, so we don't lock
|
||||
* direct_mutex here.
|
||||
*
|
||||
* Returns: zero on success. Non zero on error, which includes:
|
||||
* -EINVAL - The @ops object was not properly registered.
|
||||
*/
|
||||
int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsigned long addr)
|
||||
{
|
||||
if (check_direct_multi(ops))
|
||||
return -EINVAL;
|
||||
if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
|
||||
return -EINVAL;
|
||||
|
||||
return __modify_ftrace_direct_multi(ops, addr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(modify_ftrace_direct_multi_nolock);
|
||||
|
||||
/**
|
||||
* modify_ftrace_direct_multi - Modify an existing direct 'multi' call
|
||||
* to call something else
|
||||
* @ops: The address of the struct ftrace_ops object
|
||||
* @addr: The address of the new trampoline to call at @ops functions
|
||||
*
|
||||
* This is used to unregister currently registered direct caller and
|
||||
* register new one @addr on functions registered in @ops object.
|
||||
*
|
||||
* Note there's window between ftrace_shutdown and ftrace_startup calls
|
||||
* where there will be no callbacks called.
|
||||
*
|
||||
* Returns: zero on success. Non zero on error, which includes:
|
||||
* -EINVAL - The @ops object was not properly registered.
|
||||
*/
|
||||
int modify_ftrace_direct_multi(struct ftrace_ops *ops, unsigned long addr)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (check_direct_multi(ops))
|
||||
return -EINVAL;
|
||||
if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&direct_mutex);
|
||||
err = __modify_ftrace_direct_multi(ops, addr);
|
||||
mutex_unlock(&direct_mutex);
|
||||
return err;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user