mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
7653995537
The devres ftrace event logs the name of the devres node, which is often a
function name (e.g., "devm_work_drop") stringified by macros like
devm_add_action. Currently, ftrace stores this name as a string literal
address, which can become invalid when the module containing the string is
unloaded. This results in page faults when ftrace tries to access the name.
This behavior is problematic because the devres ftrace event is designed to
trace resource management throughout a device driver's lifecycle, including
during module unload. The event should be available even after the module
is unloaded to properly diagnose resource issues.
Fix the issue by copying the devres node name into the ftrace ring buffer
using __assign_str(), instead of storing just the address. This ensures
that ftrace can always access the name, even if the module is unloaded.
This change increases the memory usage for each of the ftrace entry by
12-16 bytes assuming the average devres node name is 20 bytes long,
depending on the size of const char *.
Note that this change does not affect anything unless all of following
conditions are met.
- CONFIG_DEBUG_DEVRES is enabled
- ftrace tracing is enabled
- The devres event is enabled in ftrace tracing
Fixes: 09705dcb63
("devres: Enable trace events")
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Keita Morisaki <keyz@google.com>
Link: https://lore.kernel.org/r/20240928125005.714781-1-keyz@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
57 lines
1.3 KiB
C
57 lines
1.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Device core Trace Support
|
|
* Copyright (C) 2021, Intel Corporation
|
|
*
|
|
* Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
|
*/
|
|
|
|
#undef TRACE_SYSTEM
|
|
#define TRACE_SYSTEM dev
|
|
|
|
#if !defined(__DEV_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
|
|
#define __DEV_TRACE_H
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/tracepoint.h>
|
|
#include <linux/types.h>
|
|
|
|
DECLARE_EVENT_CLASS(devres,
|
|
TP_PROTO(struct device *dev, const char *op, void *node, const char *name, size_t size),
|
|
TP_ARGS(dev, op, node, name, size),
|
|
TP_STRUCT__entry(
|
|
__string(devname, dev_name(dev))
|
|
__field(struct device *, dev)
|
|
__field(const char *, op)
|
|
__field(void *, node)
|
|
__string(name, name)
|
|
__field(size_t, size)
|
|
),
|
|
TP_fast_assign(
|
|
__assign_str(devname);
|
|
__entry->op = op;
|
|
__entry->node = node;
|
|
__assign_str(name);
|
|
__entry->size = size;
|
|
),
|
|
TP_printk("%s %3s %p %s (%zu bytes)", __get_str(devname),
|
|
__entry->op, __entry->node, __get_str(name), __entry->size)
|
|
);
|
|
|
|
DEFINE_EVENT(devres, devres_log,
|
|
TP_PROTO(struct device *dev, const char *op, void *node, const char *name, size_t size),
|
|
TP_ARGS(dev, op, node, name, size)
|
|
);
|
|
|
|
#endif /* __DEV_TRACE_H */
|
|
|
|
/* this part has to be here */
|
|
|
|
#undef TRACE_INCLUDE_PATH
|
|
#define TRACE_INCLUDE_PATH .
|
|
|
|
#undef TRACE_INCLUDE_FILE
|
|
#define TRACE_INCLUDE_FILE trace
|
|
|
|
#include <trace/define_trace.h>
|