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

📄 extent40.c

📁 reiser4progs ReiserFS V4 ReiserFs官方已经关闭 这个是1.0.6 2006-02-22发布的 给需要的朋友
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (C) 2001-2005 by Hans Reiser, licensing governed by   reiser4progs/COPYING.      extent40.c -- reiser4 default extent plugin. */#ifdef HAVE_CONFIG_H#  include <config.h>#endif#include "extent40.h"#include "extent40_repair.h"reiser4_core_t *extent40_core = NULL;/* Returns number of units in passed extent @place */uint32_t extent40_units(reiser4_place_t *place) {	aal_assert("umka-1446", place != NULL);#ifdef ENABLE_DEBUG	if (place->len % sizeof(extent40_t) != 0) {		aal_error("Node (%llu), item (%u): Invalid extent "			  "item size (%u) detected.", place_blknr(place),			  place->pos.item, place->len);		return 0;	}#endif		return place->len / sizeof(extent40_t);}/* Calculates extent size. */uint64_t extent40_offset(reiser4_place_t *place, uint32_t pos) {	extent40_t *extent;	uint64_t blocks = 0;	uint32_t i;    	aal_assert("umka-2204", place != NULL);		extent = extent40_body(place);		for (i = 0; i < pos; i++, extent++)		blocks += et40_get_width(extent);    	return blocks * place_blksize(place);}/* Builds the key of the unit at @pos and stores it inside passed @key   variable. It is needed for updating item key after shifting, etc. */static errno_t extent40_fetch_key(reiser4_place_t *place, reiser4_key_t *key) {	aal_assert("vpf-623", key != NULL);	aal_assert("vpf-622", place != NULL);	return body40_get_key(place, place->pos.unit,			      key, extent40_offset);}#ifndef ENABLE_MINIMAL/* Returns item size in bytes */static uint64_t extent40_size(reiser4_place_t *place) {	uint32_t units = extent40_units(place);	return extent40_offset(place, units);}/* Returns actual item size on disk */static uint64_t extent40_bytes(reiser4_place_t *place) {	extent40_t *extent;	uint64_t i, blocks;    	aal_assert("umka-2204", place != NULL);		extent = extent40_body(place);		/* Count only valuable units. */	for (blocks = 0, i = 0; i < extent40_units(place);	     i++, extent++)	{		if (et40_get_start(extent))			blocks += et40_get_width(extent);	}    	return (blocks * place_blksize(place));}/* Gets the number of unit specified offset lies in. */uint32_t extent40_unit(reiser4_place_t *place, uint64_t offset) {	uint32_t i;        uint32_t width = 0;        extent40_t *extent;                                                                                                 extent = extent40_body(place);                                                                                                 for (i = 0; i < extent40_units(place); i++, extent++) {                width += et40_get_width(extent) * place_blksize(place);                if (offset < width)                        return i;        }        return i;}/* Removes @count byte from passed @place at @pos */static errno_t extent40_remove_units(reiser4_place_t *place, trans_hint_t *hint) {	uint32_t len;	uint32_t pos;	uint32_t units;	void *src, *dst;	aal_assert("vpf-941", place != NULL);	aal_assert("umka-2402", hint != NULL);	pos = place->pos.unit;	units = extent40_units(place);		/* Check for unit pos. */	if (pos == MAX_UINT32)		pos = 0;	aal_assert("umka-3026",		   pos + hint->count <= units);		/* Calling @hint->region_func for removed region in order to let higher	   levels know that some extent region is released and perform some	   actions like release blocks in block allocator, etc. */	if (hint->region_func) {		extent40_t *extent;		uint32_t start;		uint32_t width;		uint32_t i;		extent = extent40_body(place) + pos;					for (i = pos; i < pos + hint->count; i++, extent++) {			errno_t res;						start = et40_get_start(extent);			width = et40_get_width(extent);			if (start != EXTENT_HOLE_UNIT) {				if ((res = extent40_core->tree_ops.inc_free(					place->node->tree, width)))				{					return res;				}			}			if (start == EXTENT_UNALLOC_UNIT || 			    start == EXTENT_HOLE_UNIT)				continue;						if ((res = hint->region_func(start, width, hint->data)))				return res;		}	}	/* Removing units from @pos to @hint->count. */	dst = extent40_body(place) + pos;	src = extent40_body(place) + pos +		hint->count;	len = place->len - (pos + hint->count) *		sizeof(extent40_t);				aal_memmove(dst, src, len);	/* Updating item's key by key of first unit. */	if (pos == 0) {		if (extent40_fetch_key(place, &place->key))			return -EINVAL;	}	hint->overhead = 0;	hint->len = sizeof(extent40_t) * hint->count;	place_mkdirty(place);	return 0;}/* Truncates extent item stating from left by @hint->count bytes. */static int64_t extent40_trunc_units(reiser4_place_t *place,				    trans_hint_t *hint){	int32_t size;	uint32_t epos;	uint32_t skip;	uint64_t count;	uint64_t esize;	uint64_t offset;	uint32_t blksize;		reiser4_key_t key;	extent40_t *extent;		aal_assert("umka-2458", place != NULL);	aal_assert("umka-2461", hint != NULL);	hint->len = 0;	hint->bytes = 0;	hint->overhead = 0;		/* Check for unit pos. */	if (place->pos.unit == MAX_UINT32)		place->pos.unit = 0;	blksize = place_blksize(place);	extent = extent40_body(place) + place->pos.unit;	offset = objcall(&hint->offset, get_offset);	/* Get the amount of bytes that cannot be cut at the start. */	skip = (blksize - offset % blksize);	if (skip == blksize)		skip = 0;	/* Set the start key offset to the block border. */	offset += skip;	key = hint->offset;	objcall(&key, set_offset, offset);	/* Get the amount of bytes from @offset through the end of the item. */	offset -= objcall(&place->key, get_offset);	esize = extent40_size(place) - offset;	aal_assert("vpf-1759", offset % blksize == 0);		/* Get number of blocks to be skipped within the unit. */	epos = (offset - extent40_offset(place, place->pos.unit)) / blksize;		if (hint->count < skip)		return hint->count;		if ((count = hint->count - skip) > esize)		count = esize;	/* Loop though the units until @count of bytes are truncated. We do not	   increase @place->po.unit, because it will be the same for all ticks	   of the loop, as units will be removed fully or partially and this	   means, that @count is over. */	for (size = count; size > 0; ) {		uint32_t remove;		uint32_t start;		uint32_t width;		uint32_t eskip;		errno_t res;		uint32_t i;		width = et40_get_width(extent);		eskip = size == (int64_t)count ? epos : 0;		aal_assert("vpf-1760", eskip < width);				/* Calculating what is to be cut out. */		if ((remove = size / blksize) > width - eskip)			remove = width - eskip;				/* No one block needs to be removed anymore. */		if (remove == 0)			break;				aal_assert("vpf-1761", eskip == 0 || remove == width - eskip);		aal_assert("vpf-1762", place->pos.unit == 0 || 			   remove == width - eskip);				/* Removing unit data from the cache */		for (i = 0; i < remove; i++) {			aal_hash_table_remove(hint->blocks, &key);			offset = objcall(&key, get_offset);			objcall(&key, set_offset, (offset + blksize));		}				start = et40_get_start(extent);				if (start != EXTENT_HOLE_UNIT) {			if ((res = extent40_core->tree_ops.inc_free(				place->node->tree, remove)))			{				return res;			}		}		/* Calling region remove notification function. */		if (start != EXTENT_HOLE_UNIT && start != EXTENT_UNALLOC_UNIT) {			if ((res = hint->region_func(start + eskip, 						     remove, hint->data)))			{				return res;			}		}		if (start != EXTENT_HOLE_UNIT)			hint->bytes += remove * blksize;				/* Check if we remove whole unit. */		if (eskip) {			et40_dec_width(extent, remove);			hint->bytes += remove * blksize;		} else if (remove < width) {			if (start != EXTENT_HOLE_UNIT &&			    start != EXTENT_UNALLOC_UNIT)			{				et40_inc_start(extent, remove);			}						et40_dec_width(extent, remove);			hint->bytes += remove * blksize;		} else {			/* Here we remove whole unit. So, we count width blocks			   to be released, etc. */			hint->len += sizeof(extent40_t);			/* Taking care about the rest of extent units if we're			   bot on the last unit. */			if (place->pos.unit < extent40_units(place) - 1) {								uint32_t size = sizeof(extent40_t) *					extent40_units(place) -					(place->pos.unit + 1);								aal_memmove(extent, extent + 1, size);			}		}		size -= remove * blksize;	}	/* Updating key if it makes sense. */	if (place->pos.unit == 0 && epos == 0 && count) {		offset = objcall(&place->key, get_offset);				objcall(&place->key, set_offset, 			offset + count / blksize * blksize);	}		return count + skip;}/* Builds maximal real key in use for specified @place */errno_t extent40_maxreal_key(reiser4_place_t *place,			     reiser4_key_t *key) {	aal_assert("vpf-438", key  != NULL);	aal_assert("vpf-437", place != NULL);	return body40_maxreal_key(place, key, extent40_offset);}#endif/* Builds maximal possible key for the extent item */errno_t extent40_maxposs_key(reiser4_place_t *place,			     reiser4_key_t *key) {	aal_assert("umka-1211", place != NULL);	aal_assert("umka-1212", key != NULL);	return body40_maxposs_key(place, key);}/* Performs lookup for specified @key inside the passed @place. Result of lookup   will be stored in @pos. */lookup_t extent40_lookup(reiser4_place_t *place,			 lookup_hint_t *hint,			 lookup_bias_t bias){	uint64_t offset;	uint64_t wanted;	uint32_t i, units;	extent40_t *extent;	aal_assert("umka-1500", place != NULL);	aal_assert("umka-1501", hint != NULL);		extent = extent40_body(place);	units = extent40_units(place);	wanted = objcall(hint->key, get_offset);	offset = objcall(&place->key, get_offset);		for (i = 0; i < units; i++, extent++) {		offset += (et40_get_width(extent) * place_blksize(place));		if (offset > wanted) {			place->pos.unit = i;			return PRESENT;		}	}	place->pos.unit = units;	return (bias == FIND_CONV ? PRESENT : ABSENT);}#ifndef ENABLE_MINIMAL/* Reads @count bytes of extent data from the extent item at passed @pos into   specified @buff. Uses data cache. */static int64_t extent40_read_units(reiser4_place_t *place,				   trans_hint_t *hint){	void *buff;	uint32_t i;	errno_t res;	uint64_t read;	uint64_t count;	uint32_t blksize;		reiser4_key_t key;	aal_block_t *block;	uint64_t rel_offset;	uint64_t read_offset;	uint64_t block_offset;	aal_assert("umka-1421", place != NULL);	aal_assert("umka-1422", hint != NULL);	count = hint->count;	buff = hint->specific;		if (place->pos.unit == MAX_UINT32)		place->pos.unit = 0;	extent40_fetch_key(place, &key);	blksize = place_blksize(place);	read = count;	/* Initializing read offset */	read_offset = objcall(&hint->offset, get_offset);	rel_offset = read_offset - objcall(&key, get_offset);	/* Loop through the units until needed amount of data is read or extent	   item is over. */	for (i = place->pos.unit;	     i < extent40_units(place) && count > 0; i++)	{		uint32_t size;		extent40_t *extent;		uint64_t blk, start;		extent = extent40_body(place);		/* Calculating start block for read. */		start = et40_get_start(extent + i);		blk = start + (rel_offset / blksize);		if (start == EXTENT_HOLE_UNIT) {			/* Handle the holes. Here we fill @buff by zeros, as			   hole is detected during read. */			uint64_t width = et40_get_width(extent + i) - 				(rel_offset / blksize);						for (; width > 0 && count > 0; count -= size,				     buff += size, read_offset += size, width--)			{				uint32_t rest;				rest = blksize - (read_offset % blksize);								if ((size = count) > rest)					size = rest;				aal_memset(buff, 0, size);			}		} else while (blk < start + et40_get_width(extent + i) &&			      count > 0)		{			/* Loop though the one unit. */			uint32_t rest;			rest = blksize - (read_offset % blksize);			if ((size = count) > rest)				size = rest;			/* Initilaizing offset of block needed data lie			   in. It is needed for getting block from data			   cache. */			block_offset = read_offset - (read_offset &						      (blksize - 1));			objcall(&key, set_offset, block_offset);			/* Getting block from the cache. */			block = aal_hash_table_lookup(hint->blocks, &key);			if (!block) {				reiser4_key_t *ins_key;				/* If block is not found in cache, we				   read it and put to cache. */				aal_device_t *device = extent40_device(place);				block = aal_block_load(device, blksize, blk);				if (!block)					return -EIO;				ins_key = aal_calloc(sizeof(*ins_key), 0);				if (!ins_key)					return -ENOMEM;				aal_memcpy(ins_key, &key, sizeof(key));				aal_hash_table_insert(hint->blocks,						      ins_key, block);			}			/* Copying data from found (loaded) block to			   @buff. */			aal_memcpy(buff, block->data +				   (read_offset % blksize), size);			buff += size;			count -= size;

⌨️ 快捷键说明

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