/* This function will recover the disk and then attempt to put any recovered data on that recovered disk @param int disk - disk to recover @return void */ void recoverDisk(int disk){ // If RAID 0 do nothing besides calling the recover function disk_array_recover_disk(diskArray, disk); //Level 10 if (level == 10){ int diskToCopyFrom; // To determine if recovered disk is first or second in a pair of mirrored disks if (disk % 2){ diskToCopyFrom = disk - 1; } else{ diskToCopyFrom = disk + 1; } int i; for (i = 0; i < blockSize; i++){ char buffer[BLOCK_SIZE]; disk_array_read(diskArray, diskToCopyFrom, i, buffer); disk_array_write(diskArray, disk, i, buffer); } } //Level 4 or 5 do the same attempts at recovery else if (level == 4 || level == 5){ int i; char missingData [BLOCK_SIZE]; for (i = 0; i < blockSize; i++){ if(calculateXOR(disk,i, missingData) == -1){ return; } disk_array_write(diskArray, disk, i, missingData); } } }
/** * This function handles striping across the disks */ static int stripper(int size, int lba, char* value, short isWrite) { int rc = 0; short startFound = 0; int diskIndex = 0; int blockIndex = 0; //index of block within disk int i; short write_error = 0; //loop until address reached for(i = 0; i < size + lba; i++){ if(i == lba){ startFound = 1; } //if address reached perform read or write if(startFound == 1){ if(isWrite == 1){ //has the disk failed? if(disk_active[diskIndex] == 0) { write_error = 1; } disk_array_write(_da, diskIndex, blockIndex, value); } //Read operation else { disk_array_read(_da, diskIndex, blockIndex, buffer); //if bad disk print error message if(!disk_active[diskIndex]) { printf("ERROR "); } else { printf("%d ", *((int*)buffer)); //print output from read } } } //end if start found //if reached end of strip change disk if(++blockIndex % _strip == 0) { diskIndex += 1; if(diskIndex % _disk == 0) { diskIndex = 0; } else { blockIndex -= _strip; } } } //end size+lba for loop diskIndex = diskIndex % _disk; //inform user of write error if(write_error){ printf("ERROR "); write_error = 0; } return rc; }
/* This function will write to the disk array starting at lba, for size, and will write the pattern in the buff passed into the block @param int lba - logical block address @param int size - size of the write @param char *buff - buffer to write to each block of the disk array @return void */ void writeToArray(int lba, int size, char * buff){ //Level 0 if (level == 0) { int currentDisk, currentBlock; getPhysicalBlock(disks, lba, ¤tDisk, ¤tBlock); //successfulWrite should be 0 after all writing is complete, otherwise print error //Only want to print error once int successfulWrite = 0; while (size > 0) { successfulWrite += disk_array_write(diskArray, currentDisk, currentBlock, buff); lba ++; getPhysicalBlock(disks, lba, ¤tDisk, ¤tBlock); size --; } if (successfulWrite != 0) { fprintf(stdout, "ERROR "); } } //Level 10 else if(level == 10){ int currentDisk, currentBlock; getPhysicalBlock(disks, lba, ¤tDisk, ¤tBlock); currentDisk *= 2; //successfulWrite should be 0 after all writing is complete // Only want to print error once int successfulWrite = 0; while (size > 0) { // Status keeps track of if write to disk succeded // If we fail both, status will equal -2 int status = disk_array_write(diskArray, currentDisk, currentBlock, buff); status += disk_array_write(diskArray, currentDisk + 1, currentBlock, buff); if (status == -2){ successfulWrite = -1; } lba ++; getPhysicalBlock(disks, lba, ¤tDisk, ¤tBlock); currentDisk *= 2; size--; } if (successfulWrite != 0) { fprintf(stdout, "ERROR "); } } //Level 4 else if(level == 4){ // successfulWrite should be 0 after all writing is complete // Only want to print error once int successfulWrite = 0; int currentDisk, currentBlock; int stripeLength =(disks - 1)*strip; int i, j, k; char temp[BLOCK_SIZE]; char parityChange[BLOCK_SIZE]; while (size > 0) { int whereInStripe = lba % stripeLength; int startOfThisStripe = lba - whereInStripe; int blockOffsetOfThisStripe = (startOfThisStripe)/(disks-1); int coverTo = whereInStripe + size; int tempNum; for(i = 0; i < strip; i ++){ for (j = 0; j < BLOCK_SIZE; j++) { parityChange[j] = 0; } tempNum = i; //printf("i: %i\n", i); currentBlock = i + blockOffsetOfThisStripe; while(tempNum < stripeLength){ //printf("temp: %i\n", tempNum); currentDisk = tempNum / strip; if(tempNum >= whereInStripe && tempNum < coverTo){ if (disk_array_write(diskArray, currentDisk, currentBlock, buff)){ successfulWrite --; //write failed } for (k = 0; k < BLOCK_SIZE; k++) { parityChange[k] = parityChange[k] ^ buff[k]; } } else{ if (disk_array_read(diskArray, currentDisk, currentBlock, temp) != 0) { //error reading old data, which means we cannot update parity for this block } else{ for (k = 0; k < BLOCK_SIZE; k++) { parityChange[k] = parityChange[k] ^ temp[k]; } } } tempNum += strip; } disk_array_write(diskArray, disks-1, currentBlock, parityChange); //printf("parity %i is %i\n", i, *((int*)parityChange)); } int next = startOfThisStripe + stripeLength; size -= next - lba; lba = next; } if (successfulWrite != 0) { fprintf(stdout, "ERROR "); } } //Level 5 else if(level == 5){ // successfulWrite should be 0 after all writing is complete // Only want to print error once int successfulWrite = 0; int currentDisk, currentBlock; int stripeLength =(disks - 1)*strip; int i, j, k; int currentParityDisk; char temp[BLOCK_SIZE]; char parityChange[BLOCK_SIZE]; while (size > 0) { int whereInStripe = lba % stripeLength; int startOfThisStripe = lba - whereInStripe; int blockOffsetOfThisStripe = (startOfThisStripe)/(disks-1); int coverTo = whereInStripe + size; int tempNum; for(i = 0; i < strip; i ++){ for (j = 0; j < BLOCK_SIZE; j++) { parityChange[j] = 0; } tempNum = i; //printf("i: %i\n", i); currentBlock = i + blockOffsetOfThisStripe; currentParityDisk = (currentBlock/strip) % disks; while(tempNum < stripeLength){ //printf("temp: %i\n", tempNum); currentDisk = tempNum / strip; if (currentDisk >= currentParityDisk) { currentDisk ++; } if(tempNum >= whereInStripe && tempNum < coverTo){ if (disk_array_write(diskArray, currentDisk, currentBlock, buff)){ successfulWrite --; //write failed } for (k = 0; k < BLOCK_SIZE; k++) { parityChange[k] = parityChange[k] ^ buff[k]; } } else{ if (disk_array_read(diskArray, currentDisk, currentBlock, temp) != 0) { //error reading old data, which means we cannot update parity for this block } else{ for (k = 0; k < BLOCK_SIZE; k++) { parityChange[k] = parityChange[k] ^ temp[k]; } } } tempNum += strip; } disk_array_write(diskArray, currentParityDisk, currentBlock, parityChange); //printf("parity %i is %i\n", i, *((int*)parityChange)); } int next = startOfThisStripe + stripeLength; size -= next - lba; lba = next; } if (successfulWrite != 0) { fprintf(stdout, "ERROR "); } } //Error else{ errorMsgParse(); } }