Beispiel #1
0
/*
  Calculate the XOR of all the disks besides the one passed at the block given
  Return -1 if one of the disks required to calculate the xor is failed or if any invalid arg is passed
  the XOR'ed value is returned in the xorBlock, which is assumed to be of size BLOCK_SIZE
  As a note, this method uses additive method to calculate the parity bit
  @param int diskToSkip - either parity disk or failed disk
  @param int blockToRead - which block we want to calculate parity for
  @param char *xorBlock - pass by reference the xorBlock that will be used
  @return int - 0 on success, -1 on failure
*/
int calculateXOR(int diskToSkip, int blockToRead, char* xorBlock) {
  int i;
  for (i = 0; i < BLOCK_SIZE; i++) {
      xorBlock[i] = 0;
  }
  //The disk to skip does not exist
  if (diskToSkip >= disks) {
   return -1; 
  }
  
  //Check to make sure blockToRead is within range
  
  char temp[BLOCK_SIZE];
  
  for(i=0; i < disks; i++) {
    //Skip this diskToSkip
    if (i == diskToSkip) {
      continue; 
    }
    if (disk_array_read(diskArray, i, blockToRead, temp) != 0) {
     return -1; 
    }
    int j;
    for (j = 0; j < BLOCK_SIZE; j++) {
      xorBlock[j] = xorBlock[j] ^ temp[j];
    }
  }
  return 0;
}
Beispiel #2
0
/*
  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);
    }
  }
}
Beispiel #3
0
/**
 * 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;
}
Beispiel #4
0
/*
  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, &currentDisk, &currentBlock);
    
    //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, &currentDisk, &currentBlock);
      size --;
    }
    if (successfulWrite != 0) {
      fprintf(stdout, "ERROR "); 
    }
  }
  
  //Level 10
  else if(level == 10){
    int currentDisk, currentBlock;
    getPhysicalBlock(disks, lba, &currentDisk, &currentBlock);
    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, &currentDisk, &currentBlock);
      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();
  }
}
Beispiel #5
0
/*
  This function will read from the disk array starting at lba for size
  @param int lba - logical block address
  @param int size - size of the read
  @return void 
*/
void readFromArray(int lba, int size){
  //Level 0
  if (level == 0) {
    int currentDisk, currentBlock;
    getPhysicalBlock(disks, lba, &currentDisk, &currentBlock);
    while (size > 0) {
     char buffer[BLOCK_SIZE];
     // If read succeeds print out the value
     if(disk_array_read(diskArray, currentDisk, currentBlock, buffer) == 0){
	int* firstValue = (int*)buffer;
	fprintf(stdout, "%i ", *firstValue);
     }else{
	fprintf(stdout, "ERROR ");
     }
     lba ++;
     getPhysicalBlock(disks, lba, &currentDisk, &currentBlock);
     size --;
    }
  }
  
  //Level 10
  else if(level == 10){
    int currentDisk, currentBlock;
    getPhysicalBlock(disks, lba, &currentDisk, &currentBlock);
    currentDisk *= 2;
    
    while (size > 0){
      char buffer[BLOCK_SIZE];
      // Need to check if 1st disk in mirrored is valid
      if (disk_array_read(diskArray, currentDisk, currentBlock, buffer) == 0){
	int* firstValue = (int *)buffer;
	fprintf(stdout, "%i ", *firstValue);
      } 
      // Need to check if 2nd disk in mirrored is valid
      else if (disk_array_read(diskArray, currentDisk + 1, currentBlock, buffer) == 0){
	int* firstValue = (int *)buffer;
	fprintf(stdout, "%i ", *firstValue);
      } 
      // Otherwise value read
      else {
	fprintf(stdout, "ERROR ");
      }
      lba++;
      getPhysicalBlock(disks, lba, &currentDisk, &currentBlock);
      currentDisk *= 2;
      size --;
    }
  }
  
  //Level 4
  else if(level == 4){
    int currentDisk, currentBlock;
    getPhysicalBlock(disks, lba, &currentDisk, &currentBlock);
    
    while (size > 0) {
      char buffer[BLOCK_SIZE];
      // If read succeeds print out value
      if(disk_array_read(diskArray, currentDisk, currentBlock, buffer) == 0){
	int* firstValue = (int *)buffer;
	printf("%i ", *firstValue);
      }else{ //Try to recover disk on read fail using parity
	if (calculateXOR(currentDisk,currentBlock,buffer) ==  -1){
	  printf("ERROR ");
	}
	else{
	  int* firstValue = (int *)buffer;
	  printf("%i ", *firstValue);
	}
      }
      lba ++;
      getPhysicalBlock(disks, lba, &currentDisk, &currentBlock);
      size --;
    }
  }
  
  //Level 5
  else if(level == 5){
    int currentDisk, currentBlock;
    getPhysicalBlock(disks, lba, &currentDisk, &currentBlock);
    int currentParityDisk = (currentBlock/strip) % disks;;
    if (currentDisk >= currentParityDisk) {
      currentDisk ++;
    }
    while (size > 0) {
      char buffer[BLOCK_SIZE];
      // If read succeeds print out value
      if(disk_array_read(diskArray, currentDisk, currentBlock, buffer) == 0){
	int* firstValue = (int *)buffer;
	printf("%i ", *firstValue);
      }else{ //Try to recover disk on read fail using parity
	if (calculateXOR(currentDisk,currentBlock,buffer) ==  -1){
	  printf("ERROR ");
	}
	else{
	  int* firstValue = (int *)buffer;
	  printf("%i ", *firstValue);
	}
      }
      lba ++;
      getPhysicalBlock(disks, lba, &currentDisk, &currentBlock);
      currentParityDisk = (currentBlock/strip) % disks;;
      if (currentDisk >= currentParityDisk) {
        currentDisk ++;
      }
      size --;
    }
  }
  
  //Error
  else{
    errorMsgParse();
  }
}