⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btree.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
字号:
/* * linux/fs/hfs/btree.c * * Copyright (C) 1995-1997  Paul H. Hargrove * This file may be distributed under the terms of the GNU General Public License. * * This file contains the code to manipulate the B-tree structure. * The catalog and extents files are both B-trees. * * "XXX" in a comment is a note to myself to consider changing something. * * In function preconditions the term "valid" applied to a pointer to * a structure means that the pointer is non-NULL and the structure it * points to has all fields initialized to consistent values. * * The code in this file initializes some structures which contain * pointers by calling memset(&foo, 0, sizeof(foo)). * This produces the desired behavior only due to the non-ANSI * assumption that the machine representation of NULL is all zeros. */#include "hfs_btree.h"/*================ File-local functions ================*//* * hfs_bnode_ditch()  * * Description: *   This function deletes an entire linked list of bnodes, so it *   does not need to keep the linked list consistent as *   hfs_bnode_delete() does. *   Called by hfs_btree_init() for error cleanup and by hfs_btree_free(). * Input Variable(s): *   struct hfs_bnode *bn: pointer to the first (struct hfs_bnode) in *    the linked list to be deleted. * Output Variable(s): *   NONE * Returns: *   void * Preconditions: *   'bn' is NULL or points to a "valid" (struct hfs_bnode) with a 'prev' *    field of NULL. * Postconditions: *   'bn' and all (struct hfs_bnode)s in the chain of 'next' pointers *   are deleted, freeing the associated memory and hfs_buffer_put()ing *   the associated buffer. */static void hfs_bnode_ditch(struct hfs_bnode *bn) {	struct hfs_bnode *tmp;#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)	extern int bnode_count;#endif	while (bn != NULL) {		tmp = bn->next;#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)		hfs_warn("deleting node %d from tree %d with count %d\n",		         bn->node, (int)ntohl(bn->tree->entry.cnid), bn->count);		--bnode_count;#endif		hfs_buffer_put(bn->buf); /* safe: checks for NULL argument */		/* free all but the header */		if (bn->node) {			HFS_DELETE(bn);		}		bn = tmp;	}}/*================ Global functions ================*//* * hfs_btree_free() * * Description: *   This function frees a (struct hfs_btree) obtained from hfs_btree_init(). *   Called by hfs_put_super(). * Input Variable(s): *   struct hfs_btree *bt: pointer to the (struct hfs_btree) to free * Output Variable(s): *   NONE * Returns: *   void * Preconditions: *   'bt' is NULL or points to a "valid" (struct hfs_btree) * Postconditions: *   If 'bt' points to a "valid" (struct hfs_btree) then all (struct *    hfs_bnode)s associated with 'bt' are freed by calling *    hfs_bnode_ditch() and the memory associated with the (struct *    hfs_btree) is freed. *   If 'bt' is NULL or not "valid" an error is printed and nothing *    is changed. */void hfs_btree_free(struct hfs_btree *bt){	int lcv;	if (bt && (bt->magic == HFS_BTREE_MAGIC)) {		hfs_extent_free(&bt->entry.u.file.data_fork);		for (lcv=0; lcv<HFS_CACHELEN; ++lcv) {#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)			hfs_warn("deleting nodes from bucket %d:\n", lcv);#endif			hfs_bnode_ditch(bt->cache[lcv]);		}#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)		hfs_warn("deleting header and bitmap nodes\n");#endif		hfs_bnode_ditch(&bt->head);#if defined(DEBUG_BNODES) || defined(DEBUG_ALL)		hfs_warn("deleting root node\n");#endif		hfs_bnode_ditch(bt->root);		HFS_DELETE(bt);	} else if (bt) {		hfs_warn("hfs_btree_free: corrupted hfs_btree.\n");	}}/* * hfs_btree_init() * * Description: *   Given some vital information from the MDB (HFS superblock), *   initializes the fields of a (struct hfs_btree). * Input Variable(s): *   struct hfs_mdb *mdb: pointer to the MDB *   ino_t cnid: the CNID (HFS_CAT_CNID or HFS_EXT_CNID) of the B-tree *   hfs_u32 tsize: the size, in bytes, of the B-tree *   hfs_u32 csize: the size, in bytes, of the clump size for the B-tree * Output Variable(s): *   NONE * Returns: *   (struct hfs_btree *): pointer to the initialized hfs_btree on success, *    or NULL on failure * Preconditions: *   'mdb' points to a "valid" (struct hfs_mdb) * Postconditions: *   Assuming the inputs are what they claim to be, no errors occur *   reading from disk, and no inconsistencies are noticed in the data *   read from disk, the return value is a pointer to a "valid" *   (struct hfs_btree).  If there are errors reading from disk or *   inconsistencies are noticed in the data read from disk, then and *   all resources that were allocated are released and NULL is *   returned.	If the inputs are not what they claim to be or if they *   are unnoticed inconsistencies in the data read from disk then the *   returned hfs_btree is probably going to lead to errors when it is *   used in a non-trivial way. */struct hfs_btree * hfs_btree_init(struct hfs_mdb *mdb, ino_t cnid,				  hfs_byte_t ext[12],				  hfs_u32 tsize, hfs_u32 csize){	struct hfs_btree * bt;	struct BTHdrRec * th;	struct hfs_bnode * tmp;	unsigned int next;#if defined(DEBUG_HEADER) || defined(DEBUG_ALL)	unsigned char *p, *q;#endif	if (!mdb || !ext || !HFS_NEW(bt)) {		goto bail3;	}	bt->magic = HFS_BTREE_MAGIC;	bt->sys_mdb = mdb->sys_mdb;	bt->reserved = 0;	bt->lock = 0;	hfs_init_waitqueue(&bt->wait);	bt->dirt = 0;	memset(bt->cache, 0, sizeof(bt->cache));#if 0   /* this is a fake entry. so we don't need to initialize it. */	memset(&bt->entry, 0, sizeof(bt->entry));	hfs_init_waitqueue(&bt->entry.wait);	INIT_LIST_HEAD(&bt->entry.hash);	INIT_LIST_HEAD(&bt->entry.list);#endif	bt->entry.mdb = mdb;	bt->entry.cnid = cnid;	bt->entry.type = HFS_CDR_FIL;	bt->entry.u.file.magic = HFS_FILE_MAGIC;	bt->entry.u.file.clumpablks = (csize / mdb->alloc_blksz)						>> HFS_SECTOR_SIZE_BITS;	bt->entry.u.file.data_fork.entry = &bt->entry;	bt->entry.u.file.data_fork.lsize = tsize;	bt->entry.u.file.data_fork.psize = tsize >> HFS_SECTOR_SIZE_BITS;	bt->entry.u.file.data_fork.fork = HFS_FK_DATA;	hfs_extent_in(&bt->entry.u.file.data_fork, ext);	hfs_bnode_read(&bt->head, bt, 0, HFS_STICKY);	if (!hfs_buffer_ok(bt->head.buf)) {		goto bail2;	}	th = (struct BTHdrRec *)((char *)hfs_buffer_data(bt->head.buf) +						sizeof(struct NodeDescriptor));	/* read in the bitmap nodes (if any) */	tmp = &bt->head;	while ((next = tmp->ndFLink)) {		if (!HFS_NEW(tmp->next)) {			goto bail2;		}		hfs_bnode_read(tmp->next, bt, next, HFS_STICKY);		if (!hfs_buffer_ok(tmp->next->buf)) {			goto bail2;		}		tmp->next->prev = tmp;		tmp = tmp->next;	}	if (hfs_get_ns(th->bthNodeSize) != htons(HFS_SECTOR_SIZE)) {		hfs_warn("hfs_btree_init: bthNodeSize!=512 not supported\n");		goto bail2;	}	if (cnid == htonl(HFS_CAT_CNID)) {		bt->compare = (hfs_cmpfn)hfs_cat_compare;	} else if (cnid == htonl(HFS_EXT_CNID)) {		bt->compare = (hfs_cmpfn)hfs_ext_compare;	} else {		goto bail2;	}	bt->bthDepth  = hfs_get_hs(th->bthDepth);	bt->bthRoot   = hfs_get_hl(th->bthRoot);	bt->bthNRecs  = hfs_get_hl(th->bthNRecs);	bt->bthFNode  = hfs_get_hl(th->bthFNode);	bt->bthLNode  = hfs_get_hl(th->bthLNode);	bt->bthNNodes = hfs_get_hl(th->bthNNodes);	bt->bthFree   = hfs_get_hl(th->bthFree);	bt->bthKeyLen = hfs_get_hs(th->bthKeyLen);#if defined(DEBUG_HEADER) || defined(DEBUG_ALL)	hfs_warn("bthDepth %d\n", bt->bthDepth);	hfs_warn("bthRoot %d\n", bt->bthRoot);	hfs_warn("bthNRecs %d\n", bt->bthNRecs);	hfs_warn("bthFNode %d\n", bt->bthFNode);	hfs_warn("bthLNode %d\n", bt->bthLNode);	hfs_warn("bthKeyLen %d\n", bt->bthKeyLen);	hfs_warn("bthNNodes %d\n", bt->bthNNodes);	hfs_warn("bthFree %d\n", bt->bthFree);	p = (unsigned char *)hfs_buffer_data(bt->head.buf);	q = p + HFS_SECTOR_SIZE;	while (p < q) {		hfs_warn("%02x %02x %02x %02x %02x %02x %02x %02x "		         "%02x %02x %02x %02x %02x %02x %02x %02x\n",			 *p++, *p++, *p++, *p++, *p++, *p++, *p++, *p++,			 *p++, *p++, *p++, *p++, *p++, *p++, *p++, *p++);	}#endif	/* Read in the root if it exists.	   The header always exists, but the root exists only if the	   tree is non-empty */	if (bt->bthDepth && bt->bthRoot) {		if (!HFS_NEW(bt->root)) {			goto bail2;		}		hfs_bnode_read(bt->root, bt, bt->bthRoot, HFS_STICKY);		if (!hfs_buffer_ok(bt->root->buf)) {			goto bail1;		}	} else {		bt->root = NULL;	}	return bt; bail1:	hfs_bnode_ditch(bt->root); bail2:	hfs_bnode_ditch(&bt->head);	HFS_DELETE(bt); bail3:	return NULL;}/* * hfs_btree_commit() * * Called to write a possibly dirty btree back to disk. */void hfs_btree_commit(struct hfs_btree *bt, hfs_byte_t ext[12], hfs_lword_t size){	if (bt->dirt) {		struct BTHdrRec *th;		th = (struct BTHdrRec *)((char *)hfs_buffer_data(bt->head.buf) +						 sizeof(struct NodeDescriptor));		hfs_put_hs(bt->bthDepth,  th->bthDepth);		hfs_put_hl(bt->bthRoot,   th->bthRoot);		hfs_put_hl(bt->bthNRecs,  th->bthNRecs);		hfs_put_hl(bt->bthFNode,  th->bthFNode);		hfs_put_hl(bt->bthLNode,  th->bthLNode);		hfs_put_hl(bt->bthNNodes, th->bthNNodes);		hfs_put_hl(bt->bthFree,   th->bthFree);		hfs_buffer_dirty(bt->head.buf);		/*		 * Commit the bnodes which are not cached.		 * The map nodes don't need to be committed here because		 * they are committed every time they are changed.		 */		hfs_bnode_commit(&bt->head);		if (bt->root) {			hfs_bnode_commit(bt->root);		}			hfs_put_hl(bt->bthNNodes << HFS_SECTOR_SIZE_BITS, size);		hfs_extent_out(&bt->entry.u.file.data_fork, ext);		/* hfs_buffer_dirty(mdb->buf); (Done by caller) */		bt->dirt = 0;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -