⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftrace.c

📁 Kernel code of linux kernel
💻 C
📖 第 1 页 / 共 3 页
字号:
				type = MATCH_END_ONLY;				search_len = len - (i + 1);			} else {				if (type == MATCH_END_ONLY) {					type = MATCH_MIDDLE_ONLY;				} else {					match = i;					type = MATCH_FRONT_ONLY;				}				buff[i] = 0;				break;			}		}	}	/* keep kstop machine from running */	preempt_disable();	if (enable)		ftrace_filtered = 1;	pg = ftrace_pages_start;	while (pg) {		for (i = 0; i < pg->index; i++) {			int matched = 0;			char *ptr;			rec = &pg->records[i];			if (rec->flags & FTRACE_FL_FAILED)				continue;			kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);			switch (type) {			case MATCH_FULL:				if (strcmp(str, buff) == 0)					matched = 1;				break;			case MATCH_FRONT_ONLY:				if (memcmp(str, buff, match) == 0)					matched = 1;				break;			case MATCH_MIDDLE_ONLY:				if (strstr(str, search))					matched = 1;				break;			case MATCH_END_ONLY:				ptr = strstr(str, search);				if (ptr && (ptr[search_len] == 0))					matched = 1;				break;			}			if (matched)				rec->flags |= flag;		}		pg = pg->next;	}	preempt_enable();}static ssize_tftrace_regex_write(struct file *file, const char __user *ubuf,		   size_t cnt, loff_t *ppos, int enable){	struct ftrace_iterator *iter;	char ch;	size_t read = 0;	ssize_t ret;	if (!cnt || cnt < 0)		return 0;	mutex_lock(&ftrace_regex_lock);	if (file->f_mode & FMODE_READ) {		struct seq_file *m = file->private_data;		iter = m->private;	} else		iter = file->private_data;	if (!*ppos) {		iter->flags &= ~FTRACE_ITER_CONT;		iter->buffer_idx = 0;	}	ret = get_user(ch, ubuf++);	if (ret)		goto out;	read++;	cnt--;	if (!(iter->flags & ~FTRACE_ITER_CONT)) {		/* skip white space */		while (cnt && isspace(ch)) {			ret = get_user(ch, ubuf++);			if (ret)				goto out;			read++;			cnt--;		}		if (isspace(ch)) {			file->f_pos += read;			ret = read;			goto out;		}		iter->buffer_idx = 0;	}	while (cnt && !isspace(ch)) {		if (iter->buffer_idx < FTRACE_BUFF_MAX)			iter->buffer[iter->buffer_idx++] = ch;		else {			ret = -EINVAL;			goto out;		}		ret = get_user(ch, ubuf++);		if (ret)			goto out;		read++;		cnt--;	}	if (isspace(ch)) {		iter->filtered++;		iter->buffer[iter->buffer_idx] = 0;		ftrace_match(iter->buffer, iter->buffer_idx, enable);		iter->buffer_idx = 0;	} else		iter->flags |= FTRACE_ITER_CONT;	file->f_pos += read;	ret = read; out:	mutex_unlock(&ftrace_regex_lock);	return ret;}static ssize_tftrace_filter_write(struct file *file, const char __user *ubuf,		    size_t cnt, loff_t *ppos){	return ftrace_regex_write(file, ubuf, cnt, ppos, 1);}static ssize_tftrace_notrace_write(struct file *file, const char __user *ubuf,		     size_t cnt, loff_t *ppos){	return ftrace_regex_write(file, ubuf, cnt, ppos, 0);}static voidftrace_set_regex(unsigned char *buf, int len, int reset, int enable){	if (unlikely(ftrace_disabled))		return;	mutex_lock(&ftrace_regex_lock);	if (reset)		ftrace_filter_reset(enable);	if (buf)		ftrace_match(buf, len, enable);	mutex_unlock(&ftrace_regex_lock);}/** * ftrace_set_filter - set a function to filter on in ftrace * @buf - the string that holds the function filter text. * @len - the length of the string. * @reset - non zero to reset all filters before applying this filter. * * Filters denote which functions should be enabled when tracing is enabled. * If @buf is NULL and reset is set, all functions will be enabled for tracing. */void ftrace_set_filter(unsigned char *buf, int len, int reset){	ftrace_set_regex(buf, len, reset, 1);}/** * ftrace_set_notrace - set a function to not trace in ftrace * @buf - the string that holds the function notrace text. * @len - the length of the string. * @reset - non zero to reset all filters before applying this filter. * * Notrace Filters denote which functions should not be enabled when tracing * is enabled. If @buf is NULL and reset is set, all functions will be enabled * for tracing. */void ftrace_set_notrace(unsigned char *buf, int len, int reset){	ftrace_set_regex(buf, len, reset, 0);}static intftrace_regex_release(struct inode *inode, struct file *file, int enable){	struct seq_file *m = (struct seq_file *)file->private_data;	struct ftrace_iterator *iter;	mutex_lock(&ftrace_regex_lock);	if (file->f_mode & FMODE_READ) {		iter = m->private;		seq_release(inode, file);	} else		iter = file->private_data;	if (iter->buffer_idx) {		iter->filtered++;		iter->buffer[iter->buffer_idx] = 0;		ftrace_match(iter->buffer, iter->buffer_idx, enable);	}	mutex_lock(&ftrace_sysctl_lock);	mutex_lock(&ftraced_lock);	if (iter->filtered && ftraced_suspend && ftrace_enabled)		ftrace_run_update_code(FTRACE_ENABLE_CALLS);	mutex_unlock(&ftraced_lock);	mutex_unlock(&ftrace_sysctl_lock);	kfree(iter);	mutex_unlock(&ftrace_regex_lock);	return 0;}static intftrace_filter_release(struct inode *inode, struct file *file){	return ftrace_regex_release(inode, file, 1);}static intftrace_notrace_release(struct inode *inode, struct file *file){	return ftrace_regex_release(inode, file, 0);}static ssize_tftraced_read(struct file *filp, char __user *ubuf,		     size_t cnt, loff_t *ppos){	/* don't worry about races */	char *buf = ftraced_stop ? "disabled\n" : "enabled\n";	int r = strlen(buf);	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);}static ssize_tftraced_write(struct file *filp, const char __user *ubuf,		      size_t cnt, loff_t *ppos){	char buf[64];	long val;	int ret;	if (cnt >= sizeof(buf))		return -EINVAL;	if (copy_from_user(&buf, ubuf, cnt))		return -EFAULT;	if (strncmp(buf, "enable", 6) == 0)		val = 1;	else if (strncmp(buf, "disable", 7) == 0)		val = 0;	else {		buf[cnt] = 0;		ret = strict_strtoul(buf, 10, &val);		if (ret < 0)			return ret;		val = !!val;	}	if (val)		ftrace_enable_daemon();	else		ftrace_disable_daemon();	filp->f_pos += cnt;	return cnt;}static struct file_operations ftrace_avail_fops = {	.open = ftrace_avail_open,	.read = seq_read,	.llseek = seq_lseek,	.release = ftrace_avail_release,};static struct file_operations ftrace_failures_fops = {	.open = ftrace_failures_open,	.read = seq_read,	.llseek = seq_lseek,	.release = ftrace_avail_release,};static struct file_operations ftrace_filter_fops = {	.open = ftrace_filter_open,	.read = ftrace_regex_read,	.write = ftrace_filter_write,	.llseek = ftrace_regex_lseek,	.release = ftrace_filter_release,};static struct file_operations ftrace_notrace_fops = {	.open = ftrace_notrace_open,	.read = ftrace_regex_read,	.write = ftrace_notrace_write,	.llseek = ftrace_regex_lseek,	.release = ftrace_notrace_release,};static struct file_operations ftraced_fops = {	.open = tracing_open_generic,	.read = ftraced_read,	.write = ftraced_write,};/** * ftrace_force_update - force an update to all recording ftrace functions */int ftrace_force_update(void){	int ret = 0;	if (unlikely(ftrace_disabled))		return -ENODEV;	mutex_lock(&ftrace_sysctl_lock);	mutex_lock(&ftraced_lock);	/*	 * If ftraced_trigger is not set, then there is nothing	 * to update.	 */	if (ftraced_trigger && !ftrace_update_code())		ret = -EBUSY;	mutex_unlock(&ftraced_lock);	mutex_unlock(&ftrace_sysctl_lock);	return ret;}static void ftrace_force_shutdown(void){	struct task_struct *task;	int command = FTRACE_DISABLE_CALLS | FTRACE_UPDATE_TRACE_FUNC;	mutex_lock(&ftraced_lock);	task = ftraced_task;	ftraced_task = NULL;	ftraced_suspend = -1;	ftrace_run_update_code(command);	mutex_unlock(&ftraced_lock);	if (task)		kthread_stop(task);}static __init int ftrace_init_debugfs(void){	struct dentry *d_tracer;	struct dentry *entry;	d_tracer = tracing_init_dentry();	entry = debugfs_create_file("available_filter_functions", 0444,				    d_tracer, NULL, &ftrace_avail_fops);	if (!entry)		pr_warning("Could not create debugfs "			   "'available_filter_functions' entry\n");	entry = debugfs_create_file("failures", 0444,				    d_tracer, NULL, &ftrace_failures_fops);	if (!entry)		pr_warning("Could not create debugfs 'failures' entry\n");	entry = debugfs_create_file("set_ftrace_filter", 0644, d_tracer,				    NULL, &ftrace_filter_fops);	if (!entry)		pr_warning("Could not create debugfs "			   "'set_ftrace_filter' entry\n");	entry = debugfs_create_file("set_ftrace_notrace", 0644, d_tracer,				    NULL, &ftrace_notrace_fops);	if (!entry)		pr_warning("Could not create debugfs "			   "'set_ftrace_notrace' entry\n");	entry = debugfs_create_file("ftraced_enabled", 0644, d_tracer,				    NULL, &ftraced_fops);	if (!entry)		pr_warning("Could not create debugfs "			   "'ftraced_enabled' entry\n");	return 0;}fs_initcall(ftrace_init_debugfs);static int __init ftrace_dynamic_init(void){	struct task_struct *p;	unsigned long addr;	int ret;	addr = (unsigned long)ftrace_record_ip;	stop_machine(ftrace_dyn_arch_init, &addr, NULL);	/* ftrace_dyn_arch_init places the return code in addr */	if (addr) {		ret = (int)addr;		goto failed;	}	ret = ftrace_dyn_table_alloc();	if (ret)		goto failed;	p = kthread_run(ftraced, NULL, "ftraced");	if (IS_ERR(p)) {		ret = -1;		goto failed;	}	last_ftrace_enabled = ftrace_enabled = 1;	ftraced_task = p;	return 0; failed:	ftrace_disabled = 1;	return ret;}core_initcall(ftrace_dynamic_init);#else# define ftrace_startup()		do { } while (0)# define ftrace_shutdown()		do { } while (0)# define ftrace_startup_sysctl()	do { } while (0)# define ftrace_shutdown_sysctl()	do { } while (0)# define ftrace_force_shutdown()	do { } while (0)#endif /* CONFIG_DYNAMIC_FTRACE *//** * ftrace_kill_atomic - kill ftrace from critical sections * * This function should be used by panic code. It stops ftrace * but in a not so nice way. If you need to simply kill ftrace * from a non-atomic section, use ftrace_kill. */void ftrace_kill_atomic(void){	ftrace_disabled = 1;	ftrace_enabled = 0;#ifdef CONFIG_DYNAMIC_FTRACE	ftraced_suspend = -1;#endif	clear_ftrace_function();}/** * ftrace_kill - totally shutdown ftrace * * This is a safety measure. If something was detected that seems * wrong, calling this function will keep ftrace from doing * any more modifications, and updates. * used when something went wrong. */void ftrace_kill(void){	mutex_lock(&ftrace_sysctl_lock);	ftrace_disabled = 1;	ftrace_enabled = 0;	clear_ftrace_function();	mutex_unlock(&ftrace_sysctl_lock);	/* Try to totally disable ftrace */	ftrace_force_shutdown();}/** * register_ftrace_function - register a function for profiling * @ops - ops structure that holds the function for profiling. * * Register a function to be called by all functions in the * kernel. * * Note: @ops->func and all the functions it calls must be labeled *       with "notrace", otherwise it will go into a *       recursive loop. */int register_ftrace_function(struct ftrace_ops *ops){	int ret;	if (unlikely(ftrace_disabled))		return -1;	mutex_lock(&ftrace_sysctl_lock);	ret = __register_ftrace_function(ops);	ftrace_startup();	mutex_unlock(&ftrace_sysctl_lock);	return ret;}/** * unregister_ftrace_function - unresgister a function for profiling. * @ops - ops structure that holds the function to unregister * * Unregister a function that was added to be called by ftrace profiling. */int unregister_ftrace_function(struct ftrace_ops *ops){	int ret;	mutex_lock(&ftrace_sysctl_lock);	ret = __unregister_ftrace_function(ops);	ftrace_shutdown();	mutex_unlock(&ftrace_sysctl_lock);	return ret;}intftrace_enable_sysctl(struct ctl_table *table, int write,		     struct file *file, void __user *buffer, size_t *lenp,		     loff_t *ppos){	int ret;	if (unlikely(ftrace_disabled))		return -ENODEV;	mutex_lock(&ftrace_sysctl_lock);	ret  = proc_dointvec(table, write, file, buffer, lenp, ppos);	if (ret || !write || (last_ftrace_enabled == ftrace_enabled))		goto out;	last_ftrace_enabled = ftrace_enabled;	if (ftrace_enabled) {		ftrace_startup_sysctl();		/* we are starting ftrace again */		if (ftrace_list != &ftrace_list_end) {			if (ftrace_list->next == &ftrace_list_end)				ftrace_trace_function = ftrace_list->func;			else				ftrace_trace_function = ftrace_list_func;		}	} else {		/* stopping ftrace calls (just send to ftrace_stub) */		ftrace_trace_function = ftrace_stub;		ftrace_shutdown_sysctl();	} out:	mutex_unlock(&ftrace_sysctl_lock);	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -