📄 rf_dagfuncs.c
字号:
rf_ParityLogAppend(logData, RF_FALSE, NULL, RF_FALSE); else { RF_ETIMER_STOP(timer); RF_ETIMER_EVAL(timer); tracerec->plog_us += RF_ETIMER_VAL_US(timer); (node->wakeFunc)(node, ENOMEM); } } return(0);}/***************************************************************************************** * the execution function associated with a parity log overwrite node ****************************************************************************************/int rf_ParityLogOverwriteFunc(node) RF_DagNode_t *node;{ RF_PhysDiskAddr_t *pda = (RF_PhysDiskAddr_t *) node->params[0].p; caddr_t buf = (caddr_t) node->params[1].p; RF_ParityLogData_t *logData; RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec; RF_Etimer_t timer; if (node->dagHdr->status == rf_enable) { RF_ETIMER_START(timer); logData = rf_CreateParityLogData(RF_OVERWRITE, pda, buf, (RF_Raid_t *) (node->dagHdr->raidPtr), node->wakeFunc, (void *) node, node->dagHdr->tracerec, timer); if (logData) rf_ParityLogAppend(logData, RF_FALSE, NULL, RF_FALSE); else { RF_ETIMER_STOP(timer); RF_ETIMER_EVAL(timer); tracerec->plog_us += RF_ETIMER_VAL_US(timer); (node->wakeFunc)(node, ENOMEM); } } return(0);}#else /* RF_INCLUDE_PARITYLOGGING > 0 */int rf_ParityLogUpdateFunc(node) RF_DagNode_t *node;{ return(0);}int rf_ParityLogOverwriteFunc(node) RF_DagNode_t *node;{ return(0);}#endif /* RF_INCLUDE_PARITYLOGGING > 0 */int rf_ParityLogUpdateUndoFunc(node) RF_DagNode_t *node;{ return(0);}int rf_ParityLogOverwriteUndoFunc(node) RF_DagNode_t *node;{ return(0);}/***************************************************************************************** * the execution function associated with a NOP node ****************************************************************************************/int rf_NullNodeFunc(node) RF_DagNode_t *node;{ node->status = rf_good; return(rf_FinishNode(node, RF_THREAD_CONTEXT));}int rf_NullNodeUndoFunc(node) RF_DagNode_t *node;{ node->status = rf_undone; return(rf_FinishNode(node, RF_THREAD_CONTEXT));}/***************************************************************************************** * the execution function associated with a disk-read node ****************************************************************************************/int rf_DiskReadFuncForThreads(node) RF_DagNode_t *node;{ RF_DiskQueueData_t *req; RF_PhysDiskAddr_t *pda = (RF_PhysDiskAddr_t *)node->params[0].p; caddr_t buf = (caddr_t)node->params[1].p; RF_StripeNum_t parityStripeID = (RF_StripeNum_t)node->params[2].v; unsigned priority = RF_EXTRACT_PRIORITY(node->params[3].v); unsigned lock = RF_EXTRACT_LOCK_FLAG(node->params[3].v); unsigned unlock = RF_EXTRACT_UNLOCK_FLAG(node->params[3].v); unsigned which_ru = RF_EXTRACT_RU(node->params[3].v); RF_DiskQueueDataFlags_t flags = 0; RF_IoType_t iotype = (node->dagHdr->status == rf_enable) ? RF_IO_TYPE_READ : RF_IO_TYPE_NOP; RF_DiskQueue_t **dqs = ((RF_Raid_t *) (node->dagHdr->raidPtr))->Queues; void *b_proc = NULL; caddr_t undoBuf;#ifdef KERNEL if (node->dagHdr->bp) b_proc = (void *) ((struct buf *) node->dagHdr->bp)->b_proc;#endif /* KERNEL */ RF_ASSERT( !(lock && unlock) ); flags |= (lock) ? RF_LOCK_DISK_QUEUE : 0; flags |= (unlock) ? RF_UNLOCK_DISK_QUEUE : 0;#if RF_BACKWARD > 0 /* allocate and zero the undo buffer. * this is equivalent to copying the original buffer's contents to the undo buffer * prior to performing the disk read. * XXX hardcoded 512 bytes per sector! */ if (node->dagHdr->allocList == NULL) rf_MakeAllocList(node->dagHdr->allocList); RF_CallocAndAdd(undoBuf, 1, 512 * pda->numSector, (caddr_t), node->dagHdr->allocList);#endif /* RF_BACKWARD > 0 */ req = rf_CreateDiskQueueData(iotype, pda->startSector, pda->numSector, buf, parityStripeID, which_ru, node->wakeFunc, (void *) node, NULL, node->dagHdr->tracerec, (void *)(node->dagHdr->raidPtr), flags, b_proc); if (!req) { (node->wakeFunc)(node, ENOMEM); } else { node->dagFuncData = (void *) req; rf_DiskIOEnqueue( &(dqs[pda->row][pda->col]), req, priority ); } return(0);}/***************************************************************************************** * the execution function associated with a disk-write node ****************************************************************************************/int rf_DiskWriteFuncForThreads(node) RF_DagNode_t *node;{ RF_DiskQueueData_t *req; RF_PhysDiskAddr_t *pda = (RF_PhysDiskAddr_t *)node->params[0].p; caddr_t buf = (caddr_t)node->params[1].p; RF_StripeNum_t parityStripeID = (RF_StripeNum_t)node->params[2].v; unsigned priority = RF_EXTRACT_PRIORITY(node->params[3].v); unsigned lock = RF_EXTRACT_LOCK_FLAG(node->params[3].v); unsigned unlock = RF_EXTRACT_UNLOCK_FLAG(node->params[3].v); unsigned which_ru = RF_EXTRACT_RU(node->params[3].v); RF_DiskQueueDataFlags_t flags = 0; RF_IoType_t iotype = (node->dagHdr->status == rf_enable) ? RF_IO_TYPE_WRITE : RF_IO_TYPE_NOP; RF_DiskQueue_t **dqs = ((RF_Raid_t *) (node->dagHdr->raidPtr))->Queues; void *b_proc = NULL; caddr_t undoBuf;#ifdef KERNEL if (node->dagHdr->bp) b_proc = (void *) ((struct buf *) node->dagHdr->bp)->b_proc;#endif /* KERNEL */#if RF_BACKWARD > 0 /* This area is used only for backward error recovery experiments * First, schedule allocate a buffer and schedule a pre-read of the disk * After the pre-read, proceed with the normal disk write */ if (node->status == rf_bwd2) { /* just finished undo logging, now perform real function */ node->status = rf_fired; RF_ASSERT( !(lock && unlock) ); flags |= (lock) ? RF_LOCK_DISK_QUEUE : 0; flags |= (unlock) ? RF_UNLOCK_DISK_QUEUE : 0; req = rf_CreateDiskQueueData(iotype, pda->startSector, pda->numSector, buf, parityStripeID, which_ru, node->wakeFunc, (void *) node, NULL, node->dagHdr->tracerec, (void *) (node->dagHdr->raidPtr), flags, b_proc); if (!req) { (node->wakeFunc)(node, ENOMEM); } else { node->dagFuncData = (void *) req; rf_DiskIOEnqueue( &(dqs[pda->row][pda->col]), req, priority ); } } else { /* node status should be rf_fired */ /* schedule a disk pre-read */ node->status = rf_bwd1; RF_ASSERT( !(lock && unlock) ); flags |= (lock) ? RF_LOCK_DISK_QUEUE : 0; flags |= (unlock) ? RF_UNLOCK_DISK_QUEUE : 0; if (node->dagHdr->allocList == NULL) rf_MakeAllocList(node->dagHdr->allocList); RF_CallocAndAdd(undoBuf, 1, 512 * pda->numSector, (caddr_t), node->dagHdr->allocList); req = rf_CreateDiskQueueData(RF_IO_TYPE_READ, pda->startSector, pda->numSector, undoBuf, parityStripeID, which_ru, node->wakeFunc, (void *) node, NULL, node->dagHdr->tracerec, (void *) (node->dagHdr->raidPtr), flags, b_proc); if (!req) { (node->wakeFunc)(node, ENOMEM); } else { node->dagFuncData = (void *) req; rf_DiskIOEnqueue( &(dqs[pda->row][pda->col]), req, priority ); } } return(0);#endif /* RF_BACKWARD > 0 */ /* normal processing (rollaway or forward recovery) begins here */ RF_ASSERT( !(lock && unlock) ); flags |= (lock) ? RF_LOCK_DISK_QUEUE : 0; flags |= (unlock) ? RF_UNLOCK_DISK_QUEUE : 0; req = rf_CreateDiskQueueData(iotype, pda->startSector, pda->numSector, buf, parityStripeID, which_ru, node->wakeFunc, (void *) node, NULL, node->dagHdr->tracerec, (void *) (node->dagHdr->raidPtr), flags, b_proc); if (!req) { (node->wakeFunc)(node, ENOMEM); } else { node->dagFuncData = (void *) req; rf_DiskIOEnqueue( &(dqs[pda->row][pda->col]), req, priority ); } return(0);}/***************************************************************************************** * the undo function for disk nodes * Note: this is not a proper undo of a write node, only locks are released. * old data is not restored to disk! ****************************************************************************************/int rf_DiskUndoFunc(node) RF_DagNode_t *node;{ RF_DiskQueueData_t *req; RF_PhysDiskAddr_t *pda = (RF_PhysDiskAddr_t *)node->params[0].p; RF_DiskQueue_t **dqs = ((RF_Raid_t *) (node->dagHdr->raidPtr))->Queues; req = rf_CreateDiskQueueData(RF_IO_TYPE_NOP, 0L, 0, NULL, 0L, 0, node->wakeFunc, (void *) node, NULL, node->dagHdr->tracerec, (void *) (node->dagHdr->raidPtr), RF_UNLOCK_DISK_QUEUE, NULL); if (!req) (node->wakeFunc)(node, ENOMEM); else { node->dagFuncData = (void *) req; rf_DiskIOEnqueue( &(dqs[pda->row][pda->col]), req, RF_IO_NORMAL_PRIORITY ); } return(0);}/***************************************************************************************** * the execution function associated with an "unlock disk queue" node ****************************************************************************************/int rf_DiskUnlockFuncForThreads(node) RF_DagNode_t *node;{ RF_DiskQueueData_t *req; RF_PhysDiskAddr_t *pda = (RF_PhysDiskAddr_t *)node->params[0].p; RF_DiskQueue_t **dqs = ((RF_Raid_t *) (node->dagHdr->raidPtr))->Queues; req = rf_CreateDiskQueueData(RF_IO_TYPE_NOP, 0L, 0, NULL, 0L, 0, node->wakeFunc, (void *) node, NULL, node->dagHdr->tracerec, (void *) (node->dagHdr->raidPtr), RF_UNLOCK_DISK_QUEUE, NULL); if (!req) (node->wakeFunc)(node, ENOMEM); else { node->dagFuncData = (void *) req; rf_DiskIOEnqueue( &(dqs[pda->row][pda->col]), req, RF_IO_NORMAL_PRIORITY ); } return(0);}/***************************************************************************************** * Callback routine for DiskRead and DiskWrite nodes. When the disk op completes, * the routine is called to set the node status and inform the execution engine that * the node has fired. ****************************************************************************************/int rf_GenericWakeupFunc(node, status) RF_DagNode_t *node; int status;{ switch (node->status) { case rf_bwd1 : node->status = rf_bwd2; if (node->dagFuncData) rf_FreeDiskQueueData((RF_DiskQueueData_t *) node->dagFuncData); return(rf_DiskWriteFuncForThreads(node)); break; case rf_fired : if (status) node->status = rf_bad; else node->status = rf_good; break; case rf_recover : /* probably should never reach this case */ if (status) node->status = rf_panic; else node->status = rf_undone; break; default : RF_PANIC(); break; } if (node->dagFuncData) rf_FreeDiskQueueData((RF_DiskQueueData_t *) node->dagFuncData); return(rf_FinishNode(node, RF_INTR_CONTEXT));}/***************************************************************************************** * there are three distinct types of xor nodes * A "regular xor" is used in the fault-free case where the access spans a complete * stripe unit. It assumes that the result buffer is one full stripe unit in size, * and uses the stripe-unit-offset values that it computes from the PDAs to determine * where within the stripe unit to XOR each argument buffer. * * A "simple xor" is used in the fault-free case where the access touches only a portion * of one (or two, in some cases) stripe unit(s). It assumes that all the argument * buffers are of the same size and have the same stripe unit offset. * * A "recovery xor" is used in the degraded-mode case. It's similar to the regular * xor function except that it takes the failed PDA as an additional parameter, and * uses it to determine what portions of the argument buffers need to be xor'd into * the result buffer, and where in the result buffer they should go. ****************************************************************************************//* xor the params together and store the result in the result field. * assume the result field points to a buffer that is the size of one SU, * and use the pda params to determine where within the buffer to XOR * the input buffers. */int rf_RegularXorFunc(node) RF_DagNode_t *node;{ RF_Raid_t *raidPtr = (RF_Raid_t *)node->params[node->numParams-1].p; RF_AccTraceEntry_t *tracerec = node->dagHdr->tracerec;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -