一個exfat U盤引起的systen crash

    最近遇到一個奇葩的問題,客戶反饋,在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內存耗盡。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章