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

📄 extent.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 2 页
字号:
	build_key(&key, fork, ablock);	error = hfs_binsert(fork->entry->mdb->ext_tree, 			    HFS_BKEY(&key), &raw, sizeof(raw));	if (error) {		ext->prev->next = NULL;		HFS_DELETE(ext);		return NULL;	}	set_cache(fork, ext);	return ext;}/* * update_ext() * * Given a (struct hfs_fork) write an extent record back to disk. */static void update_ext(struct hfs_fork *fork, struct hfs_extent *ext){	struct hfs_ext_key target;	struct hfs_brec brec;	if (ext->start) {		build_key(&target, fork, ext->start);		if (!hfs_bfind(&brec, fork->entry->mdb->ext_tree,			       HFS_BKEY(&target), HFS_BFIND_WRITE)) {			write_extent(brec.data, ext);			hfs_brec_relse(&brec, NULL);		}	}}/* * zero_blocks() *  * Zeros-out 'num' allocation blocks beginning with 'start'. */static int zero_blocks(struct hfs_mdb *mdb, int start, int num) {	hfs_buffer buf;	int end;	int j;	start = mdb->fs_start + start * mdb->alloc_blksz;	end = start + num * mdb->alloc_blksz;	for (j=start; j<end; ++j) {		if (hfs_buffer_ok(buf = hfs_buffer_get(mdb->sys_mdb, j, 0))) {			memset(hfs_buffer_data(buf), 0, HFS_SECTOR_SIZE);			hfs_buffer_dirty(buf);			hfs_buffer_put(buf);		}	}	return 0;}/* * shrink_fork() * * Try to remove enough allocation blocks from 'fork' * so that it is 'ablocks' allocation blocks long.  */static void shrink_fork(struct hfs_fork *fork, int ablocks){	struct hfs_mdb *mdb = fork->entry->mdb;	struct hfs_extent *ext;	int i, error, next, count;	hfs_u32 ablksz = mdb->alloc_blksz;	next =  (fork->psize / ablksz) - 1;	ext = find_ext(fork, next);	while (ext && ext->start && (ext->start >= ablocks)) {		next = ext->start - 1;		delete_extent(fork, ext);		ext = find_ext(fork, next);	}	if (!ext) {		fork->psize = (next + 1) * ablksz;		return;	}	if ((count = next + 1 - ablocks) > 0) {		for (i=2; (i>=0) && !ext->length[i]; --i) {};		lock_bitmap(mdb);		while (count && (ext->length[i] <= count)) {			ext->end -= ext->length[i];			count -= ext->length[i];			error = hfs_clear_vbm_bits(mdb, ext->block[i],						   ext->length[i]);			if (error) {				hfs_warn("hfs_truncate: error %d freeing "				       "blocks.\n", error);			}			ext->block[i] = ext->length[i] = 0;			--i;		}		if (count) {			ext->end -= count;			ext->length[i] -= count;			error = hfs_clear_vbm_bits(mdb, ext->block[i] +						       ext->length[i], count);			if (error) {				hfs_warn("hfs_truncate: error %d freeing "				       "blocks.\n", error);			}		}		unlock_bitmap(mdb);		update_ext(fork, ext);	}	fork->psize = ablocks * ablksz;}/* * grow_fork() * * Try to add enough allocation blocks to 'fork' * so that it is 'ablock' allocation blocks long.  */static int grow_fork(struct hfs_fork *fork, int ablocks){	struct hfs_cat_entry *entry = fork->entry;	struct hfs_mdb *mdb = entry->mdb;	struct hfs_extent *ext;	int i, start, err;	hfs_u16 need, len=0;	hfs_u32 ablksz = mdb->alloc_blksz;	hfs_u32 blocks, clumpablks;	blocks = fork->psize;	need = ablocks - blocks/ablksz;	if (need < 1) { /* no need to grow the fork */		return 0;	}	/* round up to clumpsize */	if (entry->u.file.clumpablks) {		clumpablks = entry->u.file.clumpablks;	} else {		clumpablks = mdb->clumpablks;	}	need = ((need + clumpablks - 1) / clumpablks) * clumpablks;	/* find last extent record and try to extend it */	if (!(ext = find_ext(fork, blocks/ablksz - 1))) {		/* somehow we couldn't find the end of the file! */		return -1;	}	/* determine which is the last used extent in the record */	/* then try to allocate the blocks immediately following it */	for (i=2; (i>=0) && !ext->length[i]; --i) {};	if (i>=0) {		/* try to extend the last extent */		start = ext->block[i] + ext->length[i];		err = 0;		lock_bitmap(mdb);		len = hfs_vbm_count_free(mdb, start);		if (!len) {			unlock_bitmap(mdb);			goto more_extents;		}		if (need < len) {			len = need;		}		err = hfs_set_vbm_bits(mdb, start, len);		unlock_bitmap(mdb);		if (err) {			relse_ext(ext);			return -1;		}			zero_blocks(mdb, start, len);			ext->length[i] += len;		ext->end += len;		blocks = (fork->psize += len * ablksz);		need -= len;		update_ext(fork, ext);	}more_extents:	/* add some more extents */	while (need) {		len = need;		err = 0;		lock_bitmap(mdb);		start = hfs_vbm_search_free(mdb, &len);		if (need < len) {			len = need;		}		err = hfs_set_vbm_bits(mdb, start, len);		unlock_bitmap(mdb);		if (!len || err) {			relse_ext(ext);			return -1;		}		zero_blocks(mdb, start, len);		/* determine which is the first free extent in the record */		for (i=0; (i<3) && ext->length[i]; ++i) {};		if (i < 3) {			ext->block[i] = start;			ext->length[i] = len;			ext->end += len;			update_ext(fork, ext);		} else {			if (!(ext = new_extent(fork, ext, blocks/ablksz,					       start, len, ablksz))) {				lock_bitmap(mdb);				hfs_clear_vbm_bits(mdb, start, len);				unlock_bitmap(mdb);				return -1;			}		}		blocks = (fork->psize += len * ablksz);		need -= len;	}	set_cache(fork, ext);	relse_ext(ext);	return 0;}/*================ Global functions ================*//* * hfs_ext_compare() * * Description: *   This is the comparison function used for the extents B-tree.  In *   comparing extent B-tree entries, the file id is the most *   significant field (compared as unsigned ints); the fork type is *   the second most significant field (compared as unsigned chars); *   and the allocation block number field is the least significant *   (compared as unsigned ints). * Input Variable(s): *   struct hfs_ext_key *key1: pointer to the first key to compare *   struct hfs_ext_key *key2: pointer to the second key to compare * Output Variable(s): *   NONE * Returns: *   int: negative if key1<key2, positive if key1>key2, and 0 if key1==key2 * Preconditions: *   key1 and key2 point to "valid" (struct hfs_ext_key)s. * Postconditions: *   This function has no side-effects */int hfs_ext_compare(const struct hfs_ext_key *key1,		    const struct hfs_ext_key *key2){	unsigned int tmp;	int retval;	tmp = hfs_get_hl(key1->FNum) - hfs_get_hl(key2->FNum);	if (tmp != 0) {		retval = (int)tmp;	} else {		tmp = (unsigned char)key1->FkType - (unsigned char)key2->FkType;		if (tmp != 0) {			retval = (int)tmp;		} else {			retval = (int)(hfs_get_hs(key1->FABN)				       - hfs_get_hs(key2->FABN));		}	}	return retval;}/* * hfs_extent_adj() * * Given an hfs_fork shrink or grow the fork to hold the * forks logical size. */void hfs_extent_adj(struct hfs_fork *fork){	if (fork) {		hfs_u32 blks, ablocks, ablksz;		if (fork->lsize > HFS_FORK_MAX) {			fork->lsize = HFS_FORK_MAX;		}		blks = (fork->lsize+HFS_SECTOR_SIZE-1) >> HFS_SECTOR_SIZE_BITS;		ablksz = fork->entry->mdb->alloc_blksz;		ablocks = (blks + ablksz - 1) / ablksz;		if (blks > fork->psize) {			grow_fork(fork, ablocks);			if (blks > fork->psize) {				fork->lsize =					fork->psize >> HFS_SECTOR_SIZE_BITS;			}		} else if (blks < fork->psize) {			shrink_fork(fork, ablocks);		}	}}/* * hfs_extent_map() * * Given an hfs_fork and a block number within the fork, return the * number of the corresponding physical block on disk, or zero on * error. */int hfs_extent_map(struct hfs_fork *fork, int block, int create) {	int ablksz, ablock, offset, tmp;	struct hfs_extent *ext;	if (!fork || !fork->entry || !fork->entry->mdb) {		return 0;	}#if defined(DEBUG_EXTENTS) || defined(DEBUG_ALL)	hfs_warn("hfs_extent_map: ablock %d of file %d, fork %d\n",		 block, fork->entry->cnid, fork->fork);#endif	if (block < 0) {		hfs_warn("hfs_extent_map: block < 0\n");		return 0;	}	if (block > (HFS_FORK_MAX >> HFS_SECTOR_SIZE_BITS)) {		hfs_warn("hfs_extent_map: block(0x%08x) > big; cnid=%d "			 "fork=%d\n", block, fork->entry->cnid, fork->fork);		return 0;	}	ablksz = fork->entry->mdb->alloc_blksz;	offset = fork->entry->mdb->fs_start + (block % ablksz);	ablock = block / ablksz;		if (block >= fork->psize) {		if (!create || (grow_fork(fork, ablock + 1) < 0))			return 0;	}#if defined(DEBUG_EXTENTS) || defined(DEBUG_ALL)	hfs_warn("(lblock %d offset %d)\n", ablock, offset);#endif	if ((ext = find_ext(fork, ablock))) {		dump_ext("trying new: ", ext);		tmp = decode_extent(ext, ablock);		relse_ext(ext);		if (tmp >= 0) {			return tmp*ablksz + offset;		}	} 	return 0;}/* * hfs_extent_out() * * Copy the first extent record from a (struct hfs_fork) to a (struct * raw_extent), record (normally the one in the catalog entry). */void hfs_extent_out(const struct hfs_fork *fork, hfs_byte_t dummy[12]){	struct hfs_raw_extent *ext = (struct hfs_raw_extent *)dummy;	if (fork && ext) {		write_extent(ext, &fork->first);		dump_ext("extent out: ", &fork->first);	}}/* * hfs_extent_in() * * Copy an raw_extent to the 'first' and 'cache' fields of an hfs_fork. */void hfs_extent_in(struct hfs_fork *fork, const hfs_byte_t dummy[12]){	const struct hfs_raw_extent *ext =		(const struct hfs_raw_extent *)dummy;	if (fork && ext) {		read_extent(&fork->first, ext, 0);		fork->cache = &fork->first;		fork->first.count = 2;		dump_ext("extent in: ", &fork->first);	}}/*  * hfs_extent_free() * * Removes from memory all extents associated with 'fil'. */void hfs_extent_free(struct hfs_fork *fork){	if (fork) {		set_cache(fork, &fork->first);	        if (fork->first.next) {		        hfs_warn("hfs_extent_free: extents in use!\n");		}	}}

⌨️ 快捷键说明

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