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

📄 rrc_raid0.c

📁 create raid tool at linux
💻 C
📖 第 1 页 / 共 2 页
字号:
			break;		/* dsk is not in source, if it's a new disk setup the counters */		if (dsk != this->cur_disk) {			/*      fprintf(stderr, "\nChanging pass 1 sink-disk to %i\n", dsk); */			this->cur_disk = dsk;		}		/* wish from this disk */		while (can_wish_again ()		       && this->dsk_total_blocks[this->cur_disk] !=		       this->dsk_blocks_done[this->cur_disk]) {			unsigned long gblock =			    sink_driver->map_local_to_global (sink_driver->							      priv,							      this->							      disks[this->								    cur_disk].							      disk_id,							      this->							      dsk_blocks_done							      [this->							       cur_disk]);			assert (this->dsk_total_blocks[this->cur_disk] >				this->dsk_blocks_done[this->cur_disk]);			if (is_gblock_in_source (gblock)) {	/* DUH !!!  ASK ANYWAY !!!								   Why was this not caught								   ? Look for somewhere in								   the common layer where								   we might be discarding a								   read... This place is								   hardly where the error								   is */				/*				 * We wish for this block, even if it is not in the source.				 * Because maybe the disk location when mapped to sink disks				 * (sink disks overlapping with sources) is in the source, and				 * this will be caught in the common layer				 */#ifdef EXTRA_CONSISTENCY_CHECKS				int tdisk;				unsigned long tdblock;				sink_driver->				    map_global_to_local (sink_driver->priv,							 gblock, &tdisk,							 &tdblock);				assert (tdisk ==					this->disks[this->cur_disk].					disk_id);				assert (tdblock ==					this->dsk_blocks_done[this->							      cur_disk]);#endif				insert_wish (gblock);			}			this->dsk_blocks_done[this->cur_disk]++;		}	}	/* If we stopped because we have no more wishes for one round, leave */	if (!can_wish_again ())		return LDR_INCOMPLETE;	/* Pass two:	 */	while (can_wish_again ()) {		/* Pick any disk */		int dsk;		int wished = 0;		for (dsk = 0;		     can_wish_again () && dsk != this->zones[0].ndisks;		     dsk++) {			/* If there are blocks left, wish for them */			if (this->dsk_blocks_done[dsk] <			    this->dsk_total_blocks[dsk]) {				unsigned long gblock =				    sink_driver->				    map_local_to_global (sink_driver->priv,							 this->disks[dsk].							 disk_id,							 this->							 dsk_blocks_done							 [dsk]);				if (is_gblock_in_source (gblock)) {#ifdef EXTRA_CONSISTENCY_CHECKS					int tdisk;					unsigned long tdblock;					sink_driver->					    map_global_to_local					    (sink_driver->priv, gblock,					     &tdisk, &tdblock);					assert (tdisk ==						this->disks[dsk].disk_id);					assert (tdblock ==						this->						dsk_blocks_done[dsk]);#endif					insert_wish (gblock);				}				wished = 1;				this->dsk_blocks_done[dsk]++;			}		}		if (!wished && can_wish_again ()) {			for (dsk = 0; dsk != this->zones[0].ndisks; dsk++)				if (this->dsk_blocks_done[dsk] !=				    this->dsk_total_blocks[dsk]) {					fprintf (stderr,						 "\nRAID-0 requester: We think we're done on disk %i, but we aren't [%lu/%lu]!\n",						 dsk,						 this->						 dsk_blocks_done[dsk],						 this->						 dsk_total_blocks[dsk]);					return LDR_FAILED;				}/*        fprintf(stderr, "\nRAID-0 requester:  No more wishes, and we could have wished again. We're done.\n"); */			return LDR_DONE;		}	}	return LDR_INCOMPLETE;}static const char *raid0_update_super (void *thisp){	/*  raid0_driver_priv * this = (raid0_driver_priv*)thisp; */	unsigned long d;	int mdfile;	int rc;	mdu_param_t mdpar;	printf ("Updating superblocks...\n");	if (analyze_sb (&ver, mkraid, new_md_cfg, 1, 0, 0)) {		fprintf (stderr, "Error analyzing superblock.\n");		return "RAID-0 Superblock analysis error";	}	/* Tell the kernel about this */	mdfile = open (new_md_cfg->md_name, O_RDONLY);	rc =	    ioctl (mdfile, SET_ARRAY_INFO,		   (unsigned long) &new_md_cfg->array.param);	if (rc) {		fprintf (stderr,			 "Failed setting array info for device %s\n",			 new_md_cfg->md_name);		return "RAID-0 Superblock info error";	}	printf ("Array is updated with kernel.\n");	for (d = 0; d != new_md_cfg->array.param.nr_disks; d++) {		rc =		    ioctl (mdfile, ADD_NEW_DISK,			   (unsigned long) (new_md_cfg->array.disks + d));		if (rc) {			fprintf (stderr,				 "Failed adding disk %lu to array\n", d);			return "RAID-0 Superblock disk addition error";		}	}	printf	    ("Disks re-inserted in array... Hold on while starting the array...\n");	close (mdfile);	mdfile = open (new_md_cfg->md_name, O_RDWR);	/* Now run the array ! */	memset (&mdpar, 0, sizeof (mdpar));	mdpar.personality = RAID0;	mdpar.chunk_size = new_md_cfg->array.param.chunk_size;	rc = ioctl (mdfile, RUN_ARRAY, (unsigned long) &mdpar);	if (rc) {		switch (errno) {		case EBUSY:			printf ("Array %s is already running\n",				new_md_cfg->md_name);			break;		default:			perror (new_md_cfg->md_name);		}		return "RAID-0 Superblock update error";	}	close (mdfile);	return 0;}static const char *raid0_map_global_to_local (void *thisp, unsigned long gblock, int *diskid,			   unsigned long *lblock){	raid0_driver_priv *this = (raid0_driver_priv *) thisp;	unsigned long czone = 0;	unsigned long passed_gchunks = 0;	unsigned long lblock_offset = 0;	int disk;	unsigned long gchunk = gblock / this->blocks_per_chunk;	assert (diskid);	assert (lblock);	while (czone != this->n_zones	       && passed_gchunks + this->zones[czone].tchunks <= gchunk) {		passed_gchunks += this->zones[czone].tchunks;		lblock_offset +=		    this->zones[czone].tchunks /		    this->zones[czone].ndisks * this->blocks_per_chunk;		czone++;	}	if (czone == this->n_zones) {		/* If the block doesn't exist here */		return "No such block!";	}	/* The disk calculation is not a bug. The kernel just works in mysterious ways... */	disk =	    this->zones[czone].disk_nrs[gchunk %					this->zones[czone].ndisks];	*lblock =	    lblock_offset + (gchunk -			     passed_gchunks) / this->zones[czone].ndisks *	    this->blocks_per_chunk + gblock % this->blocks_per_chunk;	*diskid = this->disks[disk].disk_id;	return 0;}static voidraid0_free_blocks_above_gblock (void *thisp, unsigned long gblock){	raid0_driver_priv *this = (raid0_driver_priv *) thisp;	/*	 * Iterate over zones,  mark blocks as free if they're >= gblock	 */	int czone;	unsigned long passed_gchunks = 0;	unsigned long gchunk = gblock / this->blocks_per_chunk;	/* if there's a remainder, sink will lose a partial chunk - but who cares ? */	for (czone = 0; czone != this->n_zones; czone++) {		/* Should we free stuff in this zone ? */		if (this->zones[czone].tchunks > gchunk - passed_gchunks) {			/* Find zone offset */			unsigned long zone_offset =			    (gchunk -			     passed_gchunks) / this->zones[czone].ndisks;			/* Find disk to start with */			int disk =			    (gchunk -			     passed_gchunks) % this->zones[czone].ndisks;			/* Mark blocks free in that chunk and all following */			int freed;			unsigned long disk_block_offset =			    zone_offset * this->blocks_per_chunk;			do {				freed = 0;				for (; disk != this->zones[czone].ndisks;				     disk++) {					int disknr =					    this->zones[czone].					    disk_nrs[disk];					int diskid =					    this->disks[disknr].disk_id;					if (disk_block_offset <					    this->dsk_total_blocks[disknr]) {						unsigned long block;						freed = 1;						for (block = 0;						     block !=						     this->						     blocks_per_chunk;						     block++)							    unchecked_mark_disk_block_free							    (diskid,							     block +							     disk_block_offset);					}				}				disk = 0;				disk_block_offset +=				    this->blocks_per_chunk;			} while (freed);/*        fprintf(stderr, "Initial free freed %lu blocks\n", nr_free_blocks()); */			return;		}		passed_gchunks += this->zones[czone].tchunks;	}}static voidraid0_unfree_all_blocks (void *thisp){	raid0_driver_priv *this = (raid0_driver_priv *) thisp;	int dsk;	for (dsk = 0; dsk != this->zones[0].ndisks; dsk++) {		unsigned long block;		for (block = 0; block != this->dsk_total_blocks[dsk];		     block++)			mark_disk_block_unfree (this->disks[dsk].disk_id,						block);	}}

⌨️ 快捷键说明

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