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

📄 rrc_common.c

📁 create raid tool at linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Common interface for the level drivers * * (C) 2000 by Jakob Oestergaard * * This source is covered by the GNU GPL, the same as all Linux kernel * sources. */#include "rrc_common.h"#include "raidreconf.h"typedef struct wishlist_diskid_t {	int source_disk_id;	wish_t *wish_list;	struct wishlist_diskid_t *next;} wishlist_diskid_t;typedef struct giftlist_diskid_t {	int sink_disk_id;	fulfilled_t *gift_list;	struct giftlist_diskid_t *next;} giftlist_diskid_t;unsigned max_wishes = 0;unsigned long reconf_block_size = 0;wishlist_diskid_t *wish_lists = 0;giftlist_diskid_t *gift_lists = 0;static unsigned wish_list_length = 0;static unsigned gift_list_length = 0;static unsigned long nr_wishes_hooked = 0;static unsigned long nr_gifts_hooked = 0;static unsigned long nr_max_wishes_hooked = 0;static unsigned long nr_max_gifts_hooked = 0;/* Stuff for OOM handling... */static int is_out_of_memory = 0;#define MALLOC_TRY_SIZE (sizeof(wish_t) + sizeof(fulfilled_t) + reconf_block_size)/* Free block management */char **source_disk_free_map = 0;unsigned long *source_disk_free_size = 0;unsigned long *nr_free_disk_blocks = 0;/* Some disk management as well */int nr_unique_disks = 0;rrc_disk_t **global_disk_rrc = 0;/* Stats */static unsigned long free_friends_depth = 0;#define GOOD_READ_LENGTH 128const char *initialize_unique_disks (void){	int dsk;	global_disk_rrc =	    (rrc_disk_t **) malloc (sizeof (rrc_disk_t *) *				    (old_md_cfg->array.param.nr_disks +				     new_md_cfg->array.param.nr_disks));	if (!global_disk_rrc)		return "Out of memory allocating global disk rrc array";	for (dsk = 0; dsk != old_md_cfg->array.param.nr_disks; dsk++) {		int rdsk;		for (rdsk = nr_unique_disks; rdsk; rdsk--)			if (global_disk_rrc[rdsk - 1]->disk_id ==			    old_rrc_cfg[dsk].disk_id)				break;		if (!rdsk)			global_disk_rrc[nr_unique_disks++] =			    old_rrc_cfg + dsk;	}	for (dsk = 0; dsk != new_md_cfg->array.param.nr_disks; dsk++) {		int rdsk;		for (rdsk = nr_unique_disks; rdsk; rdsk--)			if (global_disk_rrc[rdsk - 1]->disk_id ==			    new_rrc_cfg[dsk].disk_id)				break;		if (!rdsk)			global_disk_rrc[nr_unique_disks++] =			    new_rrc_cfg + dsk;	}	fprintf (stderr, "%i unique disks detected.\n", nr_unique_disks);	return 0;}voidprint_common_stats (void){	fprintf (stderr, "Maximum friend-freeing depth: %9lu\n",		 free_friends_depth);	fprintf (stderr, "Total wishes hooked:          %9lu\n",		 nr_wishes_hooked);	fprintf (stderr, "Maximum wishes hooked:        %9lu\n",		 nr_max_wishes_hooked);	fprintf (stderr, "Total gifts hooked:           %9lu\n",		 nr_gifts_hooked);	fprintf (stderr, "Maximum gifts hooked:         %9lu\n",		 nr_max_gifts_hooked);}/* Utility routines for wish_list and gift_list handling */wish_t *wish_list_source_diskid (int diskid){	wishlist_diskid_t *wlb;	for (wlb = wish_lists; wlb; wlb = wlb->next)		if (wlb->source_disk_id == diskid)			break;	if (!wlb)		return 0;	return wlb->wish_list;}fulfilled_t *gift_list_sink_diskid (int diskid){	giftlist_diskid_t *flb;	for (flb = gift_lists; flb; flb = flb->next)		if (flb->sink_disk_id == diskid)			break;	if (!flb)		return 0;	return flb->gift_list;}voidhook_wish (wish_t * wish){	wishlist_diskid_t *wlb;	for (wlb = wish_lists; wlb; wlb = wlb->next)		if (wlb->source_disk_id == wish->source_disk_id)			break;	if (!wlb) {		wishlist_diskid_t *nwl =		    (wishlist_diskid_t *)		    malloc (sizeof (wishlist_diskid_t));		if (!nwl) {			/* XXX: Implement a safe_malloc() wish emergency pre-allocated pool */			fprintf (stderr,				 "Out of memory where we must not fail. Hope you didn't need those data anyway...\n");			abort ();		}		/* hook wish */		wish->next = 0;		nwl->wish_list = wish;		wish_list_length++;		/* hook wish list */		nwl->source_disk_id = wish->source_disk_id;		nwl->next = wish_lists;		wish_lists = nwl;		/* Account */		nr_wishes_hooked++;		if (wish_list_length > nr_max_wishes_hooked)			nr_max_wishes_hooked = wish_list_length;		return;	}	/* just hook wish */	wish->next = wlb->wish_list;	wlb->wish_list = wish;	wish_list_length++;	/* account */	nr_wishes_hooked++;	if (wish_list_length > nr_max_wishes_hooked)		nr_max_wishes_hooked = wish_list_length;}voidunhook_wish (wish_t * wish){	wishlist_diskid_t *wlb;	wish_t *pwish;	for (wlb = wish_lists; wlb; wlb = wlb->next)		if (wlb->source_disk_id == wish->source_disk_id)			break;	if (!wlb) {		fprintf (stderr,			 "\nunhook_wish() was asked to unhook a wish for a disk with no wishs. Continuing anyway.\n");		return;	}	if (wish == wlb->wish_list) {		assert (wish_list_length);		/* Unhook first wish */		wlb->wish_list = wish->next;		free (wish);		wish_list_length--;		return;	}	/* Find wish and unhook it */	for (pwish = wlb->wish_list; pwish; pwish = pwish->next)		if (pwish->next == wish)			break;	if (!pwish) {		fprintf (stderr,			 "\nunhook_wish() was asked to unhook a non-existant wish. Continuing anyway.\n");		return;	}	assert (wish_list_length);	pwish->next = wish->next;	free (wish);	wish_list_length--;}voidhook_gift (fulfilled_t * gift){	giftlist_diskid_t *flb;	for (flb = gift_lists; flb; flb = flb->next)		if (flb->sink_disk_id == gift->sink_disk_id)			break;	if (!flb) {		giftlist_diskid_t *ngl =		    (giftlist_diskid_t *)		    malloc (sizeof (giftlist_diskid_t));		if (!ngl) {			fprintf (stderr,				 "\nOut of memory when hooking gift.  Will jump into ocean.\n");			abort ();		}		/* hook gift into new disk giftlist */		ngl->gift_list = gift;		gift->next = 0;		gift_list_length++;		/* hook disk gift list */		ngl->sink_disk_id = gift->sink_disk_id;		ngl->next = gift_lists;		gift_lists = ngl;		/* Account */		nr_gifts_hooked++;		if (gift_list_length > nr_max_gifts_hooked)			nr_max_gifts_hooked = gift_list_length;		return;	}	/* just hook gift */	gift->next = flb->gift_list;	flb->gift_list = gift;	gift_list_length++;	/* Account */	nr_gifts_hooked++;	if (gift_list_length > nr_max_gifts_hooked)		nr_max_gifts_hooked = gift_list_length;}voidunhook_gift (fulfilled_t * gift){	giftlist_diskid_t *flb;	fulfilled_t *pgift;	for (flb = gift_lists; flb; flb = flb->next)		if (flb->sink_disk_id == gift->sink_disk_id)			break;	if (!flb) {		fprintf (stderr,			 "\nunhook_gift() was asked to unhook a gift for a disk with no gifts. Continuing anyway.\n");		return;	}	if (gift == flb->gift_list) {		assert (gift_list_length);		/* Unhook first gift */		flb->gift_list = gift->next;		free (gift->data);		free (gift);		gift_list_length--;		return;	}	/* Find gift and unhook it */	for (pgift = flb->gift_list; pgift; pgift = pgift->next)		if (pgift->next == gift)			break;	if (!pgift) {		fprintf (stderr,			 "\nunhook_gift() was asked to unhook a non-existant gift. Continuing anyway.\n");		return;	}	assert (gift_list_length);	pgift->next = gift->next;	free (gift->data);	free (gift);	gift_list_length--;}const char *setup_free_blocks (unsigned ndisks, rrc_disk_t * diskcfg){	int d;	source_disk_free_map = (char **) malloc (sizeof (char *) * ndisks);	if (!source_disk_free_map)		return "Cannot allocate free disk map";	source_disk_free_size =	    (unsigned long *) malloc (sizeof (unsigned long) * ndisks);	if (!source_disk_free_size)		return "Cannot allocate free disk map size array";	nr_free_disk_blocks =	    (unsigned long *) malloc (sizeof (unsigned long) * ndisks);	if (!nr_free_disk_blocks)		return		    "Cannot allocate per-disk free block accounting array";	for (d = 0; d != ndisks; d++) {		/* allocate one bit for each block */		source_disk_free_size[d] =		    (diskcfg[d].reconf_blocks + 7) / 8;		source_disk_free_map[d] =		    (char *) malloc (source_disk_free_size[d]);		if (!source_disk_free_map[d])			return			    "Cannot allocate free disk map for specific disk";		/* Initially, no blocks are free */		memset (source_disk_free_map[d], 0,			source_disk_free_size[d]);		/* Update per-disk stuff */		nr_free_disk_blocks[d] = 0;	}	fprintf (stderr, "Allocated free block map for %i disks\n",		 ndisks);	return 0;}/* The good stuff */intcan_wish_again (void){	if (is_out_of_memory)		return 0;	return wish_list_length < max_wishes;}intis_gblock_in_source (unsigned long gblock){	return gblock < source_blocks;}voidinsert_wish (unsigned long gblock){	const char *ret;	wish_t *nwish;	int source_disk_id, sink_disk_id;	unsigned long source_disk_block, sink_disk_block;	int free_on_source;	/*	 *  If block is free already, there's no need to free it.  But we	 * must check that it's free on both the source and the sink	 */	ret =	    source_driver->map_global_to_local (source_driver->priv,						gblock, &source_disk_id,						&source_disk_block);	if (ret) {		fprintf (stderr,			 "\nSource driver returned error: \"%s\". Will dump core.\n",			 ret);		abort ();	}	free_on_source =	    is_disk_block_free (source_disk_id, source_disk_block);	ret =	    sink_driver->map_global_to_local (sink_driver->priv, gblock,					      &sink_disk_id,					      &sink_disk_block);	if (ret) {		fprintf (stderr,			 "\nSink driver returned error: \"%s\". Will dump core.\n",			 ret);		abort ();	}	if (free_on_source	    && is_disk_block_free (sink_disk_id, sink_disk_block)) {/*      fprintf(stderr, "Block %lu is free already\n", gblock); */		return;	}	/* Insert wish */	nwish = (wish_t *) malloc (sizeof (wish_t));	if (!nwish) {		fprintf (stderr,			 "\nOut of memory when inserting wish. Hoping to live thru it...\n");		is_out_of_memory = 1;		return;	}	/* If this block is not free on the sink disk, insert it in the wish_list 	   ** as well. 	 */	nwish->sink_disk_id = sink_disk_id;	nwish->sink_rblock = sink_disk_block;	/* We also wish for blocks that aren't in the source...  */	if (is_gblock_in_source (gblock)) {		/* Have the source driver map the global block to source-disk,block addressing */		nwish->source_disk_id = source_disk_id;		nwish->source_rblock = source_disk_block;	}	else {		/* Blocks outside of the source are treated specially. We pretend that their source and		 * sink disks and disk blocks are identical		 */		nwish->source_disk_id = nwish->sink_disk_id;		nwish->source_rblock = nwish->sink_rblock;	}	/*	 * This may be a request to free a block from the source disks, where the	 * corrosponding location on the sink disks is not yet free.	 * The common reader will detect this case and bring two gifts from only	 * one wish.  So, worst case, we will end up with twice as many gifts	 * as we had wishes.	 */#if 0	fprintf (stderr,		 "Hooking wish: src disk %i blk %4lu  ->  sink disk %i blk %4lu\n",		 nwish->source_disk_id, nwish->source_rblock,		 nwish->sink_disk_id, nwish->sink_rblock);#endif	hook_wish (nwish);}unsigned longnr_free_blocks (void){	unsigned long ret = 0;	int d;	for (d = 0; d != old_md_cfg->array.param.nr_disks; d++) {		ret += nr_free_disk_blocks[d];/*      fprintf(stderr, "\nFree blocks in disk %i = %lu\n", d, nr_free_disk_blocks[d]); */	}	return ret;}intis_diskid_in_source (int diskid){	int d;	for (d = 0; d != old_md_cfg->array.param.nr_disks; d++)		if (old_rrc_cfg[d].disk_id == diskid)			return 1;	return 0;}intis_disk_block_free (int diskid, unsigned long block){	int disk;	unsigned long blk, ofs;	for (disk = 0; disk != old_md_cfg->array.param.nr_disks; disk++)		if (old_rrc_cfg[disk].disk_id == diskid)			break;	if (disk == old_md_cfg->array.param.nr_disks) {		/* disk is not in source, so block is free per definition */		return 1;	}	/* fast check first */	if (!nr_free_disk_blocks[disk])		return 0;	if (block >= old_rrc_cfg[disk].reconf_blocks) {		/* Block is out of scope on disk.  This must be an error as we cannot resize devices */		fprintf (stderr,			 "\nBlock %lu is out of scope in is_disk_block_free request on diskid %i\n",			 block, diskid);		/* added 9-Jan-2001 DSC */		return 0;	}	/* Then look in map */	blk = block / 8;	ofs = block % 8;	if (blk >= source_disk_free_size[disk]) {		fprintf (stderr,			 "\nA driver inquired about a free block out of range. Let's see what will happen.\n");		return 0;	}	return !!(source_disk_free_map[disk][blk] & (1 << ofs));}static voidcommon_mark_disk_block_free (int diskid, unsigned long block, int check){	int disk;	unsigned long blk, ofs;

⌨️ 快捷键说明

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