欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Rasdaemon存档diskerror错误

最编程 2024-08-13 20:52:18
...
【直播预告】上云 vs 下云:降本增笑?割韭菜?

1.main函数

int main(int argc, char *argv[])
{
	struct arguments args;
	int idx = -1;
	const struct argp_option options[] = {
		{"enable",  'e', 0, 0, "enable RAS events and exit", 0},
		{"disable", 'd', 0, 0, "disable RAS events and exit", 0},
#ifdef HAVE_SQLITE3
		{"record",  'r', 0, 0, "record events via sqlite3", 0},
#endif
		{"foreground", 'f', 0, 0, "run foreground, not daemonize"},

		{ 0, 0, 0, 0, 0, 0 }
	};
	const struct argp argp = {
		.options = options,
		.parser = parse_opt,
		.doc = TOOL_DESCRIPTION,
		.args_doc = ARGS_DOC,

	};
	memset (&args, 0, sizeof(args));

	user_hz = sysconf(_SC_CLK_TCK);

	argp_parse(&argp, argc, argv, 0,  &idx, &args);

	if (idx < 0) {
		argp_help(&argp, stderr, ARGP_HELP_STD_HELP, TOOL_NAME);
		return -1;
	}

	if (args.enable_ras) {
		int enable;

		enable = (args.enable_ras > 0) ? 1 : 0;
		toggle_ras_mc_event(enable);

		return 0;
	}

	openlog(TOOL_NAME, 0, LOG_DAEMON);
	if (!args.foreground)
		if (daemon(0,0))
			exit(EXIT_FAILURE);

	handle_ras_events(args.record_events);

	return 0;
}

使用ras-mc-ctl之前,总是会报错,需要先执行一下, rasdaemon --record 其实就是表示,错误会被记录在sqlite数据库中,否则ras-mc-ctl脚本是无法从db中导出错误日志的。

在解析完参数之后,就会调用到handle_ras_events函数,其中的record_events是错误事件的ID

2.handle_ras_events

(1)创建ras结构

struct ras_events {
	char debugfs[MAX_PATH + 1];
	char tracing[MAX_PATH + 1];
	struct pevent	*pevent;
	int		page_size;

	/* Booleans */
	unsigned	use_uptime: 1;
	unsigned        record_events: 1;

	/* For timestamp */
	time_t		uptime_diff;

	/* For ras-record */
	void		*db_priv;

	/* For the mce handler */
	struct mce_priv	*mce_priv;

	/* For ABRT socket*/
	int socketfd;

	struct event_filter *filters[NR_EVENTS];
};

申请一个这样的结构体ras_events

(2)获取tracing目录

第一步获取debufs的目录,这个是记录在/proc/mount文件中,查找debugds字段,这里可以看到是

debugfs /sys/kernel/debug debugfs rw,seclabel,relatime 0 0

最终拼接出来的tracing目录就是/sys/kernel/debug/tracing/instances/rasdaemon

(3)获取tracing timestamp

这里会打开trace_clock文件查看内核是否支持uptime的,如果支持,就从/proc/uptime中读取uptime值。这里uptime_diff = now-uptime.

(4) 申请一个pevent结构

(5)从evets/header_page中获取pagesize,其实会获取timestamp,commit, overwrite, data四个值的长度

(6)add_event_handler

rc = filter_ras_mc_event(ras, "block", "block_rq_complete", "error != 0");
	if (!rc) {
		rc = add_event_handler(ras, pevent, page_size, "block",
				       "block_rq_complete", ras_diskerror_event_handler,
					NULL, DISKERROR_EVENT);
		if (!rc)
			num_events++;
		else
			log(ALL, LOG_ERR, "Can't get traces from %s:%s\n",
			    "block", "block_rq_complete");
	}

disk是这样子的

3. add_event_handler

第一步设置filter,这里会调用filter_ras_mc_event,把events/block/block_rq_complete/filter文件设置为“error!=0”.

第二步调用add_event_handler。读取events/block/block_rq_complete/format文件中的内容,分别解析出name,ID,format, print fmt字段。

第三步调用__toggle_ras_mc_event函数

这里会把block:block_rq_complete或者!block:block_rq_complete写在/sys/kernel/debug/tracing/instances/rasdaemon/set_event文件中。

4.read_ras_event_all_cpus

这个函数中会逐个打开events/per_cpu/下的所有CPU目录中的trace_pipe_raw文件。

下面会在循环中等待文件的pipe文件的信号。

然后会针对这个CPU起一个线程,调用handle_ras_event_cpu函数去处理。

5.handle_ras_event_cpu

这个函数里面回去读取trace_pipe_raw文件中的内容,调用read_ras_event。读取之后调用parse_ras_data函数