我心目中的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<=log t ((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;
}
未完待续,实现将在后面附上:

 

 

你可能感兴趣的:(Linux)