|
@@ -326,96 +326,89 @@ ftrace_record_ip(unsigned long ip)
|
|
|
|
|
|
static int
|
|
|
__ftrace_replace_code(struct dyn_ftrace *rec,
|
|
|
- unsigned char *old, unsigned char *new, int enable)
|
|
|
+ unsigned char *nop, int enable)
|
|
|
{
|
|
|
unsigned long ip, fl;
|
|
|
+ unsigned char *call, *old, *new;
|
|
|
|
|
|
ip = rec->ip;
|
|
|
|
|
|
- if (ftrace_filtered && enable) {
|
|
|
+ /*
|
|
|
+ * If this record is not to be traced and
|
|
|
+ * it is not enabled then do nothing.
|
|
|
+ *
|
|
|
+ * If this record is not to be traced and
|
|
|
+ * it is enabled then disabled it.
|
|
|
+ *
|
|
|
+ */
|
|
|
+ if (rec->flags & FTRACE_FL_NOTRACE) {
|
|
|
+ if (rec->flags & FTRACE_FL_ENABLED)
|
|
|
+ rec->flags &= ~FTRACE_FL_ENABLED;
|
|
|
+ else
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ } else if (ftrace_filtered && enable) {
|
|
|
/*
|
|
|
- * If filtering is on:
|
|
|
- *
|
|
|
- * If this record is set to be filtered and
|
|
|
- * is enabled then do nothing.
|
|
|
- *
|
|
|
- * If this record is set to be filtered and
|
|
|
- * it is not enabled, enable it.
|
|
|
- *
|
|
|
- * If this record is not set to be filtered
|
|
|
- * and it is not enabled do nothing.
|
|
|
- *
|
|
|
- * If this record is set not to trace then
|
|
|
- * do nothing.
|
|
|
- *
|
|
|
- * If this record is set not to trace and
|
|
|
- * it is enabled then disable it.
|
|
|
- *
|
|
|
- * If this record is not set to be filtered and
|
|
|
- * it is enabled, disable it.
|
|
|
+ * Filtering is on:
|
|
|
*/
|
|
|
|
|
|
- fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE |
|
|
|
- FTRACE_FL_ENABLED);
|
|
|
+ fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED);
|
|
|
|
|
|
- if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) ||
|
|
|
- (fl == (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE)) ||
|
|
|
- !fl || (fl == FTRACE_FL_NOTRACE))
|
|
|
+ /* Record is filtered and enabled, do nothing */
|
|
|
+ if (fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED))
|
|
|
return 0;
|
|
|
|
|
|
- /*
|
|
|
- * If it is enabled disable it,
|
|
|
- * otherwise enable it!
|
|
|
- */
|
|
|
- if (fl & FTRACE_FL_ENABLED) {
|
|
|
- /* swap new and old */
|
|
|
- new = old;
|
|
|
- old = ftrace_call_replace(ip, FTRACE_ADDR);
|
|
|
+ /* Record is not filtered and is not enabled do nothing */
|
|
|
+ if (!fl)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Record is not filtered but enabled, disable it */
|
|
|
+ if (fl == FTRACE_FL_ENABLED)
|
|
|
rec->flags &= ~FTRACE_FL_ENABLED;
|
|
|
- } else {
|
|
|
- new = ftrace_call_replace(ip, FTRACE_ADDR);
|
|
|
+ else
|
|
|
+ /* Otherwise record is filtered but not enabled, enable it */
|
|
|
rec->flags |= FTRACE_FL_ENABLED;
|
|
|
- }
|
|
|
} else {
|
|
|
+ /* Disable or not filtered */
|
|
|
|
|
|
if (enable) {
|
|
|
- /*
|
|
|
- * If this record is set not to trace and is
|
|
|
- * not enabled, do nothing.
|
|
|
- */
|
|
|
- fl = rec->flags & (FTRACE_FL_NOTRACE | FTRACE_FL_ENABLED);
|
|
|
- if (fl == FTRACE_FL_NOTRACE)
|
|
|
- return 0;
|
|
|
-
|
|
|
- new = ftrace_call_replace(ip, FTRACE_ADDR);
|
|
|
- } else
|
|
|
- old = ftrace_call_replace(ip, FTRACE_ADDR);
|
|
|
-
|
|
|
- if (enable) {
|
|
|
+ /* if record is enabled, do nothing */
|
|
|
if (rec->flags & FTRACE_FL_ENABLED)
|
|
|
return 0;
|
|
|
+
|
|
|
rec->flags |= FTRACE_FL_ENABLED;
|
|
|
+
|
|
|
} else {
|
|
|
+
|
|
|
+ /* if record is not enabled do nothing */
|
|
|
if (!(rec->flags & FTRACE_FL_ENABLED))
|
|
|
return 0;
|
|
|
+
|
|
|
rec->flags &= ~FTRACE_FL_ENABLED;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ call = ftrace_call_replace(ip, FTRACE_ADDR);
|
|
|
+
|
|
|
+ if (rec->flags & FTRACE_FL_ENABLED) {
|
|
|
+ old = nop;
|
|
|
+ new = call;
|
|
|
+ } else {
|
|
|
+ old = call;
|
|
|
+ new = nop;
|
|
|
+ }
|
|
|
+
|
|
|
return ftrace_modify_code(ip, old, new);
|
|
|
}
|
|
|
|
|
|
static void ftrace_replace_code(int enable)
|
|
|
{
|
|
|
int i, failed;
|
|
|
- unsigned char *new = NULL, *old = NULL;
|
|
|
+ unsigned char *nop = NULL;
|
|
|
struct dyn_ftrace *rec;
|
|
|
struct ftrace_page *pg;
|
|
|
|
|
|
- if (enable)
|
|
|
- old = ftrace_nop_replace();
|
|
|
- else
|
|
|
- new = ftrace_nop_replace();
|
|
|
+ nop = ftrace_nop_replace();
|
|
|
|
|
|
for (pg = ftrace_pages_start; pg; pg = pg->next) {
|
|
|
for (i = 0; i < pg->index; i++) {
|
|
@@ -433,7 +426,7 @@ static void ftrace_replace_code(int enable)
|
|
|
unfreeze_record(rec);
|
|
|
}
|
|
|
|
|
|
- failed = __ftrace_replace_code(rec, old, new, enable);
|
|
|
+ failed = __ftrace_replace_code(rec, nop, enable);
|
|
|
if (failed && (rec->flags & FTRACE_FL_CONVERTED)) {
|
|
|
rec->flags |= FTRACE_FL_FAILED;
|
|
|
if ((system_state == SYSTEM_BOOTING) ||
|
|
@@ -534,8 +527,7 @@ static void ftrace_startup(void)
|
|
|
|
|
|
mutex_lock(&ftrace_start_lock);
|
|
|
ftrace_start++;
|
|
|
- if (ftrace_start == 1)
|
|
|
- command |= FTRACE_ENABLE_CALLS;
|
|
|
+ command |= FTRACE_ENABLE_CALLS;
|
|
|
|
|
|
if (saved_ftrace_func != ftrace_trace_function) {
|
|
|
saved_ftrace_func = ftrace_trace_function;
|
|
@@ -734,6 +726,9 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
|
|
|
((iter->flags & FTRACE_ITER_FAILURES) &&
|
|
|
!(rec->flags & FTRACE_FL_FAILED)) ||
|
|
|
|
|
|
+ ((iter->flags & FTRACE_ITER_FILTER) &&
|
|
|
+ !(rec->flags & FTRACE_FL_FILTER)) ||
|
|
|
+
|
|
|
((iter->flags & FTRACE_ITER_NOTRACE) &&
|
|
|
!(rec->flags & FTRACE_FL_NOTRACE))) {
|
|
|
rec = NULL;
|
|
@@ -1186,7 +1181,7 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable)
|
|
|
|
|
|
mutex_lock(&ftrace_sysctl_lock);
|
|
|
mutex_lock(&ftrace_start_lock);
|
|
|
- if (iter->filtered && ftrace_start && ftrace_enabled)
|
|
|
+ if (ftrace_start && ftrace_enabled)
|
|
|
ftrace_run_update_code(FTRACE_ENABLE_CALLS);
|
|
|
mutex_unlock(&ftrace_start_lock);
|
|
|
mutex_unlock(&ftrace_sysctl_lock);
|