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

📄 rrc_raid0.c

📁 create raid tool at linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * RAID-0 driver code for the raidreconf utility * (C) 1999,2000 by Jakob Oestergaard * * This source is covered by the GNU GPL, the same as all Linux kernel * sources. */#include "raidreconf.h"#include "rrc_common.h"typedef struct rrc_zone_t {	unsigned long tchunks;	/* total size of zone */	unsigned long ndisks;	rrc_disk_t **disks;	unsigned long *disk_nrs;	/* mapping of zone disk # into real (zone[0]) disk # */} rrc_zone_t;typedef struct raid0_driver_priv {	rrc_zone_t *zones;	rrc_disk_t *disks;	int n_zones;	unsigned long tot_chunks;	unsigned long blocks_per_chunk;	/* state for the current non-source sink-disk we're wishing for blocks to (pass 1) */	int cur_disk;		/* initialized to -1,  if it's equal to zones[0].ndisks then we're in pass 2 */	unsigned long *dsk_total_blocks;	unsigned long *dsk_blocks_done;} raid0_driver_priv;static const char *raid0_initialize (void *, md_cfg_entry_t *,				     rrc_disk_t *, unsigned long *);static driver_status_t raid0_request_blocks (void *);static const char *raid0_update_super (void *);static const char *raid0_map_global_to_local (void *, unsigned long, int *,					      unsigned long *);static unsigned long raid0_map_local_to_global (void *, int,						unsigned long);static void raid0_free_blocks_above_gblock (void *, unsigned long);static void raid0_unfree_all_blocks (void *);static intcalc_raid_zones (rrc_disk_t * disks, int ndisks, rrc_zone_t ** zones,		 int *nzones){	int i;	int current_zone_disk_size = 0;	unsigned long passed_dchunks = 0;	assert (ndisks);	*nzones = 0;	*zones = (rrc_zone_t *) malloc (sizeof (rrc_zone_t) * ndisks);	if (!*zones) {		fprintf (stderr, "Cannot alloc. zone table\n");		return 1;	}	/* Step thru disks */	for (i = 0; i != ndisks; i++) {		int d;		rrc_disk_t *smallest = 0;		for (d = 0; d != ndisks; d++) {			if (!smallest			    || ((disks[d].chunks < smallest->chunks)))				    if (disks[d].chunks >					current_zone_disk_size) smallest =					    &disks[d];		}		/* Smallest i null, or it holds the smallest disk which		 * can go into the new zone (eg. is larger than previous zone) */		if (smallest)			fprintf (stderr, "Smallest is: %lu chunks\n",				 smallest->chunks);		else			fprintf (stderr, "No smallest\n");		if (!smallest)			break;		current_zone_disk_size = smallest->chunks;		/* Now find all disks of this size or above */		(*zones)[*nzones].ndisks = 0;		(*zones)[*nzones].tchunks = 0;				    (*zones)[*nzones].disks =		    (rrc_disk_t **) malloc (sizeof (rrc_disk_t *) *					    ndisks);		(*zones)[*nzones].disk_nrs =		    (unsigned long *) malloc (sizeof (unsigned long) *					      ndisks);		if (!(*zones)[*nzones].disks		    && !(*zones)[*nzones].disk_nrs) {			fprintf (stderr,				 "zone->disk or zone->disk_nr array allocation failure\n");			return 1;		}		for (d = 0; d != ndisks; d++) {			if (disks[d].chunks >= smallest->chunks) {				fprintf (stderr,					 "Adding disk %i to zone %i as disk # %lu\n",					 d, *nzones,					 (*zones)[*nzones].ndisks);				(*zones)[*nzones].disks[(*zones)[*nzones].							ndisks] =				    &disks[d];				(*zones)[*nzones].				    disk_nrs[(*zones)[*nzones].ndisks] = d;				(*zones)[*nzones].ndisks++;								    (*zones)[*nzones].tchunks +=				    smallest->chunks - passed_dchunks;			}		}		fprintf (stderr, "Size of zone %i is %lu chunks.\n",			 *nzones, (*zones)[*nzones].tchunks);		(*nzones)++;		current_zone_disk_size++;		passed_dchunks = smallest->chunks;	}	return 0;}/* returns the global block number from a sink disk id and disk-block */static unsigned longraid0_map_local_to_global (void *thisp, int diskid, unsigned long dblock){	raid0_driver_priv *this = (raid0_driver_priv *) thisp;	unsigned long passed_gblocks = 0;	unsigned long passed_dblocks = 0;	unsigned long czone = 0;	while (czone < this->n_zones) {		/* Is dchunk in this zone ? */		if (this->zones[czone].tchunks * this->blocks_per_chunk /		    this->zones[czone].ndisks > dblock - passed_dblocks) {			unsigned long stripe_index;			/* Find the stripe index that yield disk as the disk number */			for (stripe_index = 0;			     stripe_index != this->zones[czone].ndisks;			     stripe_index++) {				if (this->				    disks[this->zones[czone].					  disk_nrs[						   (passed_gblocks /						    this->						    blocks_per_chunk +						    stripe_index) %						   this->zones[czone].						   ndisks]].disk_id ==				    diskid) break;			}			if (stripe_index == this->zones[czone].ndisks) {				fprintf (stderr,					 "Bummer! No stripe index yields disk id %i as destination\nWill dump core.\n",					 diskid);				abort ();			}			/* global block = passed gblocks blocks			 *  + zone disks * ((disk block - passed disk blocks) / blocks per chunk * blocks per chunk)			 *  + disk index * blocks per chunk 			 *  + (disk block - passed disk blocks) % blocks per chunk			 */			assert (dblock / this->blocks_per_chunk -				passed_dblocks / this->blocks_per_chunk ==				(dblock -				 passed_dblocks) / this->blocks_per_chunk);			return passed_gblocks + (dblock -						 passed_dblocks) /			    this->blocks_per_chunk *			    this->blocks_per_chunk *			    this->zones[czone].ndisks +			    stripe_index * this->blocks_per_chunk +			    (dblock -			     passed_dblocks) % this->blocks_per_chunk;		}		else {			/* Nope */			/*      fprintf(stderr, "Chunk %lu is not in zone %lu\n", dchunk, czone); */			passed_dblocks +=			    this->zones[czone].tchunks /			    this->zones[czone].ndisks *			    this->blocks_per_chunk;			passed_gblocks +=			    this->zones[czone].tchunks *			    this->blocks_per_chunk;			czone++;		}	}	/* BUG! */	fprintf (stderr,		 "Ouch ! block %lu on disk id %i is not in array!\nWill dump core.\n",		 dblock, diskid);	abort ();}level_driver_t *new_raid0_driver (void){	level_driver_t *drv =	    (level_driver_t *) malloc (sizeof (level_driver_t));	raid0_driver_priv *priv =	    (raid0_driver_priv *) malloc (sizeof (raid0_driver_priv));	if (!drv || !priv)		return 0;	drv->initialize = raid0_initialize;	drv->request_blocks = raid0_request_blocks;	drv->update_super = raid0_update_super;	drv->map_global_to_local = raid0_map_global_to_local;	drv->map_local_to_global = raid0_map_local_to_global;	drv->free_blocks_above_gblock = raid0_free_blocks_above_gblock;	drv->unfree_all_blocks = raid0_unfree_all_blocks;	drv->priv = priv;	priv->zones = 0;	priv->disks = 0;	priv->n_zones = 0;	priv->tot_chunks = 0;	priv->blocks_per_chunk = 0;	priv->cur_disk = -1;	priv->dsk_total_blocks = 0;	priv->dsk_blocks_done = 0;	return drv;}static const char *raid0_initialize (void *thisp, md_cfg_entry_t * cfg, rrc_disk_t * cfgdisks,		  unsigned long *blocks){	raid0_driver_priv *this = (raid0_driver_priv *) thisp;	unsigned long d;	/* Calculate zones */	if (calc_raid_zones	    (cfgdisks, cfg->array.param.nr_disks, &this->zones,	     &this->n_zones)) {		return "Zone calculation failed!";	}	this->disks = cfgdisks;	this->tot_chunks = 0;	for (d = 0; d != this->n_zones; d++)		this->tot_chunks += this->zones[d].tchunks;	this->blocks_per_chunk =	    (cfg->array.param.chunk_size / MD_BLK_SIZ) / reconf_block_size;	*blocks = this->blocks_per_chunk * this->tot_chunks;	this->dsk_total_blocks =	    (unsigned long *) malloc (sizeof (unsigned long) *				      cfg->array.param.nr_disks);	if (!this->dsk_total_blocks)		return "Cannot allocate disk blocks array";	for (d = 0; d != cfg->array.param.nr_disks; d++)		this->dsk_total_blocks[d] =		    cfgdisks[d].chunks * this->blocks_per_chunk;	this->dsk_blocks_done =	    (unsigned long *) malloc (sizeof (unsigned long) *				      cfg->array.param.nr_disks);	if (!this->dsk_blocks_done)		return "Cannot allocate disk blocks done array";	for (d = 0; d != cfg->array.param.nr_disks; d++)		this->dsk_blocks_done[d] = 0;	fprintf (stderr,		 "RAID0 Array size: %lu blocks (%lu Chunks) on %i disks\n",		 this->blocks_per_chunk * this->tot_chunks,		 this->tot_chunks, cfg->array.param.nr_disks);	return 0;}/* * This routine will fill in the wish_list with wishes for blocks it would * like to write. */static driver_status_traid0_request_blocks (void *thisp){	raid0_driver_priv *this = (raid0_driver_priv *) thisp;	/* Pass 1:	 *  Find disk not in {source}	 *    Request blocks from disk until no more wishes or disk is full	 *	 *  If no more wishes, return LDR_INCOMPLETE	 *	 * Pass 2:	 *  While more wishes && still blocks left to write	 *     For each disk in {sink}	 *        Find max. number of contigous blocks, and wish for them (until sequence done or no more wishes)	 *	 *  If no more wishes, return LDR_INCOMPLETE	 *  If there are still blocks that aren't marked free, return LDR_INCOMPLETE	 *  Otherwise return LDR_DONE	 */	/* Pass 1: */	assert (this->zones);	while (can_wish_again ()	       && this->cur_disk != this->zones[0].ndisks) {		int dsk = this->cur_disk;		/* if we have no disk, or if we just finished the one we had... */		if (this->cur_disk == -1		    || this->dsk_total_blocks[dsk] ==		    this->dsk_blocks_done[dsk]) {			/* pick next disk, don't exceed number of disks, keep picking next until we fail or reach a good one */			for (dsk++; dsk != this->zones[0].ndisks; dsk++) {				if (!is_diskid_in_source				    (this->disks[dsk].disk_id)) break;			}		}		/* if there are no more non-source disks to read from, skip to pass two */		if (dsk == this->zones[0].ndisks)

⌨️ 快捷键说明

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