您当前的位置:首页 > 计算机 > 精彩资源

一个exfat U盘引起的systen crash

时间:04-17来源:作者:点击数:

最近遇到一个奇葩的问题,客户反馈,在Android 系统的TV上,插入exfat格式的U盘,然后就system crash了,经过一系列分析后,我们找到了原因,把分析过程分享下,希望对有类似的问题的朋友参考:

由于kernel打印的信息比较多,我们截取比较重要的信息分析:

这里out_of_memory了, 内存耗尽了,我们继续看看下面的打印,看看是哪个进程导致的内存消耗

这里我们发现了fsck.exfat进程消耗了比较大的内存, 213754*4k(page size)=834M, 我们是1G的内存

为了验证fsck.exfat在校验过程的内存消耗,我们保存从插入U盘,到system crash过程的内存消耗

从插入U盘后,我们可以看到fsck.exfat后台消耗的内存在一直增加,最后消耗到800M+后就system crash了.

由于fsck.exfat 标准的开源的文件系统校验工具,应该不存在问题,我们备份了U盘的内容,打算把U盘格式化下,再验证,就在我们备份U盘内容的时候,发现了U盘的问题,其中某个文件异常了,出现了无限循环的路径地址, Windows电脑弹出了提示信息:

就是这个文件,我们在备份的时候异常了,貌似有个无限循环的路径地址,是不是就是这个原因导致的我们的fsck出问题了呢,我们查看下fsck.exfat的源码:

static void dirck(struct exfat* ef, const char* path)
{
	struct exfat_node* parent;
	struct exfat_node* node;
	struct exfat_iterator it;
	int rc;
	size_t path_length;
	char* entry_path;

	if (exfat_lookup(ef, &parent, path) != 0)
		exfat_bug("directory `%s' is not found", path);
	if (!(parent->flags & EXFAT_ATTRIB_DIR))
		exfat_bug("`%s' is not a directory (0x%x)", path, parent->flags);

	path_length = strlen(path);
	entry_path = malloc(path_length + 1 + EXFAT_NAME_MAX);
	if (entry_path == NULL)
	{
		exfat_error("out of memory");
		return;
	}
	strcpy(entry_path, path);
	strcat(entry_path, "/");

	rc = exfat_opendir(ef, parent, &it);
	if (rc != 0)
	{
		free(entry_path);
		exfat_put_node(ef, parent);
		exfat_error("failed to open directory `%s'", path);
		return;
	}
	while ((node = exfat_readdir(ef, &it)))
	{
		exfat_get_name(node, entry_path + path_length + 1, EXFAT_NAME_MAX);
		exfat_debug("%s: %s, %"PRIu64" bytes, cluster %u", entry_path,
				IS_CONTIGUOUS(*node) ? "contiguous" : "fragmented",
				node->size, node->start_cluster);
		if (node->flags & EXFAT_ATTRIB_DIR)
		{
			directories_count++;
			dirck(ef, entry_path);
		}
		else
			files_count++;
		nodeck(ef, node);
		exfat_put_node(ef, node);
	}
	exfat_closedir(ef, &it);
	exfat_put_node(ef, parent);
	free(entry_path);
}

static void fsck(struct exfat* ef)
{
	exfat_print_info(ef->sb, exfat_count_free_clusters(ef));
	dirck(ef, "");
}

显然,在fsck的时候,会调用dirck函数, 这个函数会递归运行,遇到这种无限循环的目录,肯定就出不来了,每次进入dirck函数都会malloc分配内存,这样就会导致内存耗尽,好像是这么回事。

我们把U盘格式化后,在插入板上,问题消失了,系统能够正常挂载exfat的U盘了,到此,问题找到了。这个是由于U盘文件系统管理出问题,导致的无限循环的目录,引发了fsck.exfat内存耗尽。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门