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

📄 rf_evenodd_dagfuncs.c

📁 RAIDFrame是个非常好的磁盘阵列RAID仿真工具
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1995 Carnegie-Mellon University. * All rights reserved. * * Author: ChangMing Wu * * Permission to use, copy, modify and distribute this software and * its documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU *  School of Computer Science *  Carnegie Mellon University *  Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. *//* * Code for RAID-EVENODD  architecture. */#include "rf_types.h"#include "rf_raid.h"#include "rf_dag.h"#include "rf_dagffrd.h"#include "rf_dagffwr.h"#include "rf_dagdegrd.h"#include "rf_dagdegwr.h"#include "rf_dagutils.h"#include "rf_dagfuncs.h"#include "rf_threadid.h"#include "rf_etimer.h"#include "rf_general.h"#include "rf_configure.h"#include "rf_parityscan.h"#include "rf_sys.h"#include "rf_evenodd.h"#include "rf_evenodd_dagfuncs.h"/* These redundant functions are for small write */RF_RedFuncs_t rf_EOSmallWritePFuncs = { rf_RegularXorFunc, "Regular Old-New P", rf_SimpleXorFunc, "Simple Old-New P" };RF_RedFuncs_t rf_EOSmallWriteEFuncs = { rf_RegularONEFunc, "Regular Old-New E", rf_SimpleONEFunc, "Regular Old-New E" }; /* These redundant functions are for degraded read */RF_RedFuncs_t rf_eoPRecoveryFuncs =  { rf_RecoveryXorFunc, "Recovery Xr", rf_RecoveryXorFunc, "Recovery Xr"};RF_RedFuncs_t rf_eoERecoveryFuncs = { rf_RecoveryEFunc, "Recovery E Func", rf_RecoveryEFunc, "Recovery E Func" };/********************************************************************************************** *   the following encoding node functions is used in  EO_000_CreateLargeWriteDAG  **********************************************************************************************/int rf_RegularPEFunc(node)  RF_DagNode_t  *node;{   rf_RegularESubroutine(node,node->results[1]);      rf_RegularXorFunc(node);    /* does the wakeup here! */}/************************************************************************************************ *  For EO_001_CreateSmallWriteDAG, there are (i)RegularONEFunc() and (ii)SimpleONEFunc() to *  be used. The previous case is when write access at least sectors of full stripe unit. *  The later function is used when the write access two stripe units but with total sectors *  less than sectors per SU. In this case, the access of parity and 'E' are shown as disconnected *  areas in their stripe unit and  parity write and 'E' write are both devided into two distinct *  writes( totally four). This simple old-new write and regular old-new write happen as in RAID-5 ************************************************************************************************//* Algorithm:      1. Store the difference of old data and new data in the Rod buffer.     2. then encode this buffer into the buffer which already have old 'E' information inside it, 	the result can be shown to be the new 'E' information.     3. xor the Wnd buffer into the difference buffer to recover the  original old data.   Here we have another alternative: to allocate a temporary buffer for storing the difference of    old data and new data, then encode temp buf into old 'E' buf to form new 'E', but this approach    take the same speed as the previous, and need more memory.*/int rf_RegularONEFunc(node)  RF_DagNode_t  *node;{  RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams-1].p;  RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) &raidPtr->Layout;  int EpdaIndex = (node->numParams-1)/2 - 1; /* the parameter of node where you can find e-pda */   int i, k, retcode = 0;  int suoffset, length;  RF_RowCol_t scol;  char *srcbuf, *destbuf;  RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;  RF_Etimer_t timer;  RF_PhysDiskAddr_t *pda, *EPDA = (RF_PhysDiskAddr_t *) node->params[EpdaIndex].p;   int ESUOffset = rf_StripeUnitOffset(layoutPtr, EPDA->startSector); /* generally zero  */  RF_ASSERT( EPDA->type == RF_PDA_TYPE_Q );  RF_ASSERT(ESUOffset == 0);  RF_ETIMER_START(timer);   /* Xor the Wnd buffer into Rod buffer, the difference of old data and new data is stored in Rod buffer */  for( k=0; k< EpdaIndex; k += 2) {   length = rf_RaidAddressToByte(raidPtr, ((RF_PhysDiskAddr_t *)node->params[k].p)->numSector );   retcode = rf_bxor( node->params[k+EpdaIndex+3].p, node->params[k+1].p, length, node->dagHdr->bp);     }  /* Start to encoding the buffer storing the difference of old data and new data into 'E' buffer  */  for (i=0; i<EpdaIndex; i+=2) if (node->params[i+1].p != node->results[0]) { /* results[0] is buf ptr of E */    pda = (RF_PhysDiskAddr_t *) node->params[i].p;    srcbuf = (char *) node->params[i+1].p;    scol = rf_EUCol(layoutPtr, pda->raidAddress );    suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);    destbuf = ((char *) node->results[0]) + rf_RaidAddressToByte(raidPtr,suoffset);     rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);  }  /* Recover the original old data to be used by parity encoding function in XorNode */  for( k=0; k< EpdaIndex; k += 2) {   length = rf_RaidAddressToByte(raidPtr, ((RF_PhysDiskAddr_t *)node->params[k].p)->numSector );   retcode = rf_bxor( node->params[k+EpdaIndex+3].p, node->params[k+1].p, length, node->dagHdr->bp);  }  RF_ETIMER_STOP(timer);  RF_ETIMER_EVAL(timer);  tracerec->q_us += RF_ETIMER_VAL_US(timer);  rf_GenericWakeupFunc(node, 0);  }int rf_SimpleONEFunc(node)  RF_DagNode_t   *node;{  RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams-1].p;  RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) &raidPtr->Layout;  RF_PhysDiskAddr_t *pda = (RF_PhysDiskAddr_t *) node->params[0].p;  int i, retcode = 0;  char *srcbuf, *destbuf;  RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;  int length;  RF_RowCol_t scol;  RF_Etimer_t timer;  RF_ASSERT( ((RF_PhysDiskAddr_t *)node->params[2].p)->type == RF_PDA_TYPE_Q );  if (node->dagHdr->status == rf_enable) {      RF_ETIMER_START(timer);     length = rf_RaidAddressToByte(raidPtr, ((RF_PhysDiskAddr_t *)node->params[4].p)->numSector );/* this is a pda of writeDataNodes */     /* bxor to buffer of readDataNodes */     retcode = rf_bxor( node->params[5].p, node->params[1].p, length, node->dagHdr->bp);     /* find out the corresponding colume in encoding matrix for write colume to be encoded into redundant disk 'E' */     scol = rf_EUCol(layoutPtr, pda->raidAddress );      srcbuf = node->params[1].p;     destbuf = node->params[3].p;     /* Start encoding process */     rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);        rf_bxor( node->params[5].p, node->params[1].p, length, node->dagHdr->bp);     RF_ETIMER_STOP(timer); RF_ETIMER_EVAL(timer); tracerec->q_us += RF_ETIMER_VAL_US(timer);   }  return(rf_GenericWakeupFunc(node, retcode));     /* call wake func explicitly since no I/O in this node */}/****** called by rf_RegularPEFunc(node) and rf_RegularEFunc(node) in f.f. large write  ********/void rf_RegularESubroutine(node, ebuf)  RF_DagNode_t  *node;  char          *ebuf;{  RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams-1].p;  RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) &raidPtr->Layout;  RF_PhysDiskAddr_t *pda;  int i, suoffset;  RF_RowCol_t scol;  char *srcbuf, *destbuf;  RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;  RF_Etimer_t timer;  RF_ETIMER_START(timer);  for (i=0; i<node->numParams-2; i+=2) {    RF_ASSERT( node->params[i+1].p != ebuf );    pda = (RF_PhysDiskAddr_t *) node->params[i].p;    suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);    scol = rf_EUCol(layoutPtr, pda->raidAddress );    srcbuf = (char *) node->params[i+1].p;    destbuf = ebuf + rf_RaidAddressToByte(raidPtr, suoffset );    rf_e_encToBuf(raidPtr,  scol, srcbuf, RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);  }  RF_ETIMER_STOP(timer);  RF_ETIMER_EVAL(timer);  tracerec->xor_us += RF_ETIMER_VAL_US(timer);}/******************************************************************************************* *			 Used in  EO_001_CreateLargeWriteDAG                       ******************************************************************************************/int rf_RegularEFunc(node)    RF_DagNode_t  *node;{   rf_RegularESubroutine(node, node->results[0]);     rf_GenericWakeupFunc(node, 0);}/******************************************************************************************* * This degraded function allow only two case:  *  1. when write access the full failed stripe unit, then the access can be more than  *     one tripe units. *  2. when write access only part of the failed SU, we assume accesses of more than  *     one stripe unit is not allowed so that the write can be dealt with like a  *     large write.  *  The following function is based on these assumptions. So except in the second case,  *  it looks the same as a large write encodeing function. But this is not exactly the *  normal way for doing a degraded write, since raidframe have to break cases of access  *  other than the above two into smaller accesses. We may have to change  *  DegrESubroutin in the future.   *******************************************************************************************/void rf_DegrESubroutine(node, ebuf)  RF_DagNode_t  *node;  char          *ebuf;{  RF_Raid_t *raidPtr = (RF_Raid_t *) node->params[node->numParams-1].p;  RF_RaidLayout_t *layoutPtr = (RF_RaidLayout_t *) &raidPtr->Layout;  RF_PhysDiskAddr_t *failedPDA = (RF_PhysDiskAddr_t *) node->params[node->numParams-2].p;  RF_PhysDiskAddr_t *pda;  int i, suoffset, failedSUOffset = rf_StripeUnitOffset(layoutPtr, failedPDA->startSector);  RF_RowCol_t scol;  char *srcbuf, *destbuf;  RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;  RF_Etimer_t timer;  RF_ETIMER_START(timer);  for (i=0; i<node->numParams-2; i+=2) {    RF_ASSERT( node->params[i+1].p != ebuf );    pda = (RF_PhysDiskAddr_t *) node->params[i].p;    suoffset = rf_StripeUnitOffset(layoutPtr, pda->startSector);    scol = rf_EUCol(layoutPtr, pda->raidAddress );    srcbuf = (char *) node->params[i+1].p;    destbuf = ebuf + rf_RaidAddressToByte(raidPtr, suoffset-failedSUOffset);    rf_e_encToBuf(raidPtr, scol, srcbuf, RF_EO_MATRIX_DIM - 2, destbuf, pda->numSector);  }  RF_ETIMER_STOP(timer); RF_ETIMER_EVAL(timer); tracerec->q_us += RF_ETIMER_VAL_US(timer);}/************************************************************************************** * This function is used in case where one data disk failed and both redundant disks  * alive. It is used in the EO_100_CreateWriteDAG. Note: if there is another disk * failed in the stripe but not accessed at this time, then we should, instead, use * the rf_EOWriteDoubleRecoveryFunc(). **************************************************************************************/int rf_Degraded_100_EOFunc(node)  RF_DagNode_t  *node;{  rf_DegrESubroutine(node, node->results[1]);  rf_RecoveryXorFunc(node);  /* does the wakeup here! */}/************************************************************************************** * This function is to encode one sector in one of the data disks to the E disk. * However, in evenodd this function can also be used as decoding function to recover  * data from dead disk in the case of parity failure and a single data failure. **************************************************************************************/void rf_e_EncOneSect(  RF_RowCol_t   srcLogicCol,  char         *srcSecbuf,  RF_RowCol_t   destLogicCol,  char         *destSecbuf,  int           bytesPerSector){  int S_index;  /* index of the EU in the src col which need be Xored into all EUs in a dest sector */  int numRowInEncMatix = (RF_EO_MATRIX_DIM) -1;   RF_RowCol_t j, indexInDest,   /* row index of an encoding unit in the destination colume of encoding matrix */              indexInSrc;  /* row index of an encoding unit in the source colume used for recovery */  int bytesPerEU = bytesPerSector/numRowInEncMatix;#if RF_EO_MATRIX_DIM > 17  int shortsPerEU = bytesPerEU/sizeof(short);  short *destShortBuf, *srcShortBuf1, *srcShortBuf2;  register short temp1;#elif RF_EO_MATRIX_DIM == 17  int longsPerEU = bytesPerEU/sizeof(long);  long *destLongBuf, *srcLongBuf1, *srcLongBuf2;  register long temp1;#endif#if RF_EO_MATRIX_DIM > 17  RF_ASSERT( sizeof(short) == 2 || sizeof(short) == 1 );

⌨️ 快捷键说明

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