📄 rrc_raid0.c
字号:
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 + -