我心目中的UBIFS之wandering tree

雖然我很想將我之前的一個工業檢測的小項目(圖像算法)接着做完,但是還是決定將UBIFS系統的一些概念的地方完成!

那麼廢話少說,直奔主題!

Wandering tree,遊離樹,暫且這樣翻譯,毋庸置疑的它就是一棵B+樹:

B+樹一般作爲文件系統的數據結構,與平衡二叉查找樹-紅黑樹的主要區別在於子女的個數,具體由Flash的特性決定:

由上圖得出B+樹的定義:

一棵m階的B+樹:
1.有n棵子樹的結點中含有n個關鍵字。
2.所有的葉子結點中包含了全部關鍵字的信息,及指向含這些關鍵字記錄的指針,且葉子結點本身依關鍵字的大小自小而大順序鏈接。
3.所有的非終端結點可以看成是索引部分,結點中僅含其子樹(根結點)中的最大(或最小)關鍵字。
通常在B+樹上有兩個頭指針,一個指向根結點,一個指向關鍵字最小的葉子結點。
 
定理:如果n>=1,則對任意一棵包含n個關鍵字,高度爲h,最小度數t>=2的B樹T,有h<=logt((n+1)/2)
說明:t是指每個結點能包含的關鍵字數的上界和下界
t>=2,最小包含2個關鍵字,上圖的10與20在第2 level不再爲關鍵字,圖中標出了而已
每個非根節點至少t-1個關鍵字,至少有t個子女,至多2t-1個關鍵字,最多也就2t個子女,根結點至少包含一個關鍵字
 
Linux kernel構建B+ tree的算法如下:
/**
 * struct btree_head - btree head
 *
 * @node: the first node in the tree
 * @mempool: mempool used for node allocations
 * @height: current of the tree
 */
struct btree_head {
	unsigned long *node;
	mempool_t *mempool;
	int height;
};
static int btree_insert_level(struct btree_head *head, struct btree_geo *geo,
			      unsigned long *key, void *val, int level,
			      gfp_t gfp)
{
	unsigned long *node;
	int i, pos, fill, err;

	BUG_ON(!val);
	if (head->height < level) {
		err = btree_grow(head, geo, gfp);
		if (err)
			return err;
	}

retry:
	node = find_level(head, geo, key, level);
	pos = getpos(geo, node, key);
	fill = getfill(geo, node, pos);
	/* two identical keys are not allowed */
	BUG_ON(pos < fill && keycmp(geo, node, pos, key) == 0);

	if (fill == geo->no_pairs) {
		/* need to split node */
		unsigned long *new;

		new = btree_node_alloc(head, gfp);
		if (!new)
			return -ENOMEM;
		err = btree_insert_level(head, geo,
				bkey(geo, node, fill / 2 - 1),
				new, level + 1, gfp);
		if (err) {
			mempool_free(new, head->mempool);
			return err;
		}
		for (i = 0; i < fill / 2; i++) {
			setkey(geo, new, i, bkey(geo, node, i));
			setval(geo, new, i, bval(geo, node, i));
			setkey(geo, node, i, bkey(geo, node, i + fill / 2));
			setval(geo, node, i, bval(geo, node, i + fill / 2));
			clearpair(geo, node, i + fill / 2);
		}
		if (fill & 1) {
			setkey(geo, node, i, bkey(geo, node, fill - 1));
			setval(geo, node, i, bval(geo, node, fill - 1));
			clearpair(geo, node, fill - 1);
		}
		goto retry;
	}
	BUG_ON(fill >= geo->no_pairs);

	/* shift and insert */
	for (i = fill; i > pos; i--) {
		setkey(geo, node, i, bkey(geo, node, i - 1));
		setval(geo, node, i, bval(geo, node, i - 1));
	}
	setkey(geo, node, pos, key);
	setval(geo, node, pos, val);

	return 0;
}
未完待續,實現將在後面附上:

 

 

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