Beispiel #1
0
static void _InsertToEntry(uffs_Device *dev, u16 *entry,
						   int hash, TreeNode *node)
{
	node->hash_next = entry[hash];
	node->hash_prev = EMPTY_NODE;
	if (entry[hash] != EMPTY_NODE) {
		FROM_IDX(entry[hash], TPOOL(dev))->hash_prev = TO_IDX(node, TPOOL(dev));
	}
	entry[hash] = TO_IDX(node, TPOOL(dev));
}
Beispiel #2
0
TreeNode * uffs_TreeFindDirNodeByName(uffs_Device *dev,
									  const char *name, u32 len,
									  u16 sum, u16 parent)
{
	int i;
	u16 x;
	TreeNode *node;
	struct uffs_TreeSt *tree = &(dev->tree);
	
	for (i = 0; i < DIR_NODE_ENTRY_LEN; i++) {
		x = tree->dir_entry[i];
		while (x != EMPTY_NODE) {
			node = FROM_IDX(x, TPOOL(dev));
			if (node->u.dir.checksum == sum &&
					node->u.dir.parent == parent) {
				//read file name from flash, and compare...
				if (uffs_TreeCompareFileName(dev, name, len, sum,
											node, UFFS_TYPE_DIR) == U_TRUE) {
					//Got it!
					return node;
				}
			}
			x = node->hash_next;
		}
	}

	return NULL;

}
Beispiel #3
0
/* calculate file length, etc */
static URET _BuildTreeStepThree(uffs_Device *dev)
{
	int i;
	u16 x;
	TreeNode *work;
	TreeNode *node;
	struct uffs_TreeSt *tree;
	uffs_Pool *pool;
	u16 blockSave;

	TreeNode *cache = NULL;
	u16 cacheSerial = INVALID_UFFS_SERIAL;

	tree = &(dev->tree);
	pool = TPOOL(dev);

	uffs_Perror(UFFS_MSG_NOISY, "build tree step three");

	for (i = 0; i < DATA_NODE_ENTRY_LEN; i++) {
		x = tree->data_entry[i];
		while (x != EMPTY_NODE) {
			work = FROM_IDX(x, pool);
			if (work->u.data.parent == cacheSerial) {
				node = cache;
			}
			else {
				node = uffs_TreeFindFileNode(dev, work->u.data.parent);
				cache = node;
				cacheSerial = work->u.data.parent;
			}
			if (node == NULL) {
				x = work->hash_next;
				//this data block does not belong to any file ?
				//should be erased.
				uffs_Perror(UFFS_MSG_NORMAL,
					"find a orphan data block:%d, "
					"parent:%d, serial:%d, will be erased!",
					work->u.data.block,
					work->u.data.parent, work->u.data.serial);

				uffs_BreakFromEntry(dev, UFFS_TYPE_DATA, work);
				blockSave = work->u.data.block;
				work->u.list.block = blockSave;
				uffs_FlashEraseBlock(dev, blockSave);
				if (HAVE_BADBLOCK(dev))
					uffs_BadBlockProcess(dev, work);
				else
					uffs_TreeInsertToErasedListTail(dev, work);
			}
			else {
				node->u.file.len += work->u.data.len;
				x = work->hash_next;
			}
		}
	}

	return U_SUCC;
}
Beispiel #4
0
TreeNode * uffs_TreeFindDataNodeByBlock(uffs_Device *dev, u16 block)
{
	int hash;
	TreeNode *node;
	struct uffs_TreeSt *tree = &(dev->tree);
	u16 x;

	for (hash = 0; hash < DATA_NODE_ENTRY_LEN; hash++) {
		x = tree->data_entry[hash];
		while (x != EMPTY_NODE) {
			node = FROM_IDX(x, TPOOL(dev));
			if (node->u.data.block == block)
				return node;
			x = node->hash_next;
		}
	}

	return NULL;
}
Beispiel #5
0
TreeNode * uffs_TreeFindDirNode(uffs_Device *dev, u16 serial)
{
	int hash;
	u16 x;
	TreeNode *node;
	struct uffs_TreeSt *tree = &(dev->tree);

	hash = serial & DIR_NODE_HASH_MASK;
	x = tree->dir_entry[hash];
	while (x != EMPTY_NODE) {
		node = FROM_IDX(x, TPOOL(dev));
		if (node->u.dir.serial == serial) {
			return node;
		}
		else {
			x = node->hash_next;
		}
	}
	return NULL;
}
Beispiel #6
0
TreeNode * uffs_TreeFindDataNode(uffs_Device *dev, u16 parent, u16 serial)
{
	int hash;
	TreeNode *node;
	struct uffs_TreeSt *tree = &(dev->tree);
	u16 x;

	hash = GET_DATA_HASH(parent, serial);
	x = tree->data_entry[hash];
	while(x != EMPTY_NODE) {
		node = FROM_IDX(x, TPOOL(dev));

		if(node->u.data.parent == parent &&
			node->u.data.serial == serial)
				return node;

		x = node->hash_next;
	}

	return NULL;
}
Beispiel #7
0
TreeNode * uffs_TreeFindDirNodeWithParent(uffs_Device *dev, u16 parent)
{
	int hash;
	u16 x;
	TreeNode *node;
	struct uffs_TreeSt *tree = &(dev->tree);

	for (hash = 0; hash < DIR_NODE_ENTRY_LEN; hash++) {
		x = tree->dir_entry[hash];
		while (x != EMPTY_NODE) {
			node = FROM_IDX(x, TPOOL(dev));
			if (node->u.dir.parent == parent) {
				return node;
			}
			else {
				x = node->hash_next;
			}
		}
	}
	
	return NULL;
}
Beispiel #8
0
static URET _BuildTreeStepOne(uffs_Device *dev)
{
	int block_lt;
	uffs_BlockInfo *bc = NULL;
	TreeNode *node;
	struct uffs_TreeSt *tree;
	uffs_Pool *pool;
	struct uffs_MiniHeaderSt header;
	URET ret = U_SUCC;
	struct BlockTypeStatSt st = {0, 0, 0};
	
	tree = &(dev->tree);
	pool = TPOOL(dev);

	tree->bad = NULL;
	tree->bad_count = 0;
	tree->erased = NULL;
	tree->erased_tail = NULL;
	tree->erased_count = 0;

	uffs_Perror(UFFS_MSG_NOISY, "build tree step one");

//	printf("s:%d e:%d\n", dev->par.start, dev->par.end);
	for (block_lt = dev->par.start; block_lt <= dev->par.end; block_lt++) {
		bc = uffs_BlockInfoGet(dev, block_lt);
		if (bc == NULL) {
			uffs_Perror(UFFS_MSG_SERIOUS, "step one:fail to get block info");
			ret = U_FAIL;
			break;
		}
		node = (TreeNode *)uffs_PoolGet(pool);
		if (node == NULL) {
			uffs_Perror(UFFS_MSG_SERIOUS, "insufficient tree node!");
			ret = U_FAIL;
			break;
		}

		// Need to check bad block at first !
		if (uffs_FlashIsBadBlock(dev, block_lt) == U_TRUE) {
			node->u.list.block = block_lt;
			uffs_TreeInsertToBadBlockList(dev, node);
			uffs_Perror(UFFS_MSG_NORMAL, "found bad block %d", block_lt);
		}
		else if (uffs_IsPageErased(dev, bc, 0) == U_TRUE) { //@ read one spare: 0
			// page 0 tag shows it's an erased block, we need to check the mini header status to make sure it is clean.
			if (uffs_LoadMiniHeader(dev, block_lt, 0, &header) == U_FAIL) {
				uffs_Perror(UFFS_MSG_SERIOUS,
							"I/O error when reading mini header !"
							"block %d page %d",
							block_lt, 0);
				ret = U_FAIL;
				break;
			}

			if (header.status != 0xFF) {
				// page 0 tag is clean but page data is dirty ???
				// this block should be erased immediately !
				uffs_FlashEraseBlock(dev, block_lt);
			}
			node->u.list.block = block_lt;
			if (HAVE_BADBLOCK(dev)) {
				uffs_Perror(UFFS_MSG_NORMAL,
							"New bad block (%d) discovered.", block_lt);
				uffs_BadBlockProcess(dev, node);
			}
			else {
				// page 0 is clean does not means all pages in this block are clean,
				// need to check this block later before use it.
				uffs_TreeInsertToErasedListTailEx(dev, node, 1);
			}
		}
		else {
			
			// this block have valid data page(s).

			ret = _ScanAndFixUnCleanPage(dev, bc);
			if (ret == U_FAIL)
				break;

			ret = _BuildValidTreeNode(dev, node, bc, &st);
			if (ret == U_FAIL)
				break;

		}
		uffs_BlockInfoPut(dev, bc);
	} //end of for

	if(ret == U_FAIL) 
		uffs_BlockInfoPut(dev, bc);

	uffs_Perror(UFFS_MSG_NORMAL,
				"DIR %d, FILE %d, DATA %d", st.dir, st.file, st.data);

	return ret;
}
Beispiel #9
0
static URET do_FindObject(uffs_FindInfo *f, uffs_ObjectInfo *info, u16 x)
{
	URET ret = U_SUCC;
	TreeNode *node;
	uffs_Device *dev = f->dev;

	if (f->step == 0) 
	{ //!< working on dirs
		while (x != EMPTY_NODE) 
		{
			node = FROM_IDX(x, TPOOL(dev));
			if (node->u.dir.parent == f->serial) 
			{
				f->work = node;
				f->pos++;
				if (info)
					ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_DIR, NULL);
				goto ext;
			}
			x = node->hash_next;
		}

		f->hash++; //come to next hash entry

		for (; f->hash < DIR_NODE_ENTRY_LEN; f->hash++) 
		{
			x = dev->tree.dir_entry[f->hash];
			while (x != EMPTY_NODE) 
			{
				node = FROM_IDX(x, TPOOL(dev));
				if (node->u.dir.parent == f->serial) 
				{
					f->work = node;
					f->pos++;
					if (info)
						ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_DIR, NULL);
					goto ext;
				}
				x = node->hash_next;
			}
		}

		//no subdirs, then lookup files ..
		f->step++;
		f->hash = 0;
		x = EMPTY_NODE;
	}

	if (f->step == 1) 
	{

		while (x != EMPTY_NODE) 
		{
			node = FROM_IDX(x, TPOOL(dev));
			if (node->u.file.parent == f->serial) 
			{
				f->work = node;
				f->pos++;
				if (info)
					ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_FILE, NULL);
				goto ext;
			}
			x = node->hash_next;
		}

		f->hash++; //come to next hash entry

		for (; f->hash < FILE_NODE_ENTRY_LEN; f->hash++) 
		{
			x = dev->tree.file_entry[f->hash];
			while (x != EMPTY_NODE) 
			{
				node = FROM_IDX(x, TPOOL(dev));
				if (node->u.file.parent == f->serial) 
				{
					f->work = node;
					f->pos++;
					if (info) 
						ret = _LoadObjectInfo(dev, node, info, UFFS_TYPE_FILE, NULL);
					goto ext;
				}
				x = node->hash_next;
			}
		}

		//no any files, stopped.
		f->step++;
	}

	ret = U_FAIL;
ext:

	return ret;

}