📄 rf_reconstruct.c
字号:
RF_LOCK_MUTEX(raidPtr->recon_done_proc_mutex); for(p=raidPtr->recon_done_procs;p;p=p->next) { p->proc(raidPtr, p->arg); } RF_UNLOCK_MUTEX(raidPtr->recon_done_proc_mutex);}int rf_RegisterReconDoneProc( RF_Raid_t *raidPtr, void (*proc)(), void *arg, RF_ReconDoneProc_t **handlep){ RF_ReconDoneProc_t *p; RF_FREELIST_GET(rf_rdp_freelist,p,next,(RF_ReconDoneProc_t *)); if (p == NULL) return(ENOMEM); p->proc = proc; p->arg = arg; RF_LOCK_MUTEX(raidPtr->recon_done_proc_mutex); p->next = raidPtr->recon_done_procs; raidPtr->recon_done_procs = p; RF_UNLOCK_MUTEX(raidPtr->recon_done_proc_mutex); if (handlep) *handlep = p; return(0);}/***************************************************************************************** * * sets up the parameters that will be used by the reconstruction process * currently there are none, except for those that the layout-specific * configuration (e.g. rf_ConfigureDeclustered) routine sets up. * * in the kernel, we fire off the recon thread. * ****************************************************************************************/static void rf_ShutdownReconstruction(ignored) void *ignored;{ RF_FREELIST_DESTROY(rf_recond_freelist,next,(RF_RaidReconDesc_t *)); RF_FREELIST_DESTROY(rf_rdp_freelist,next,(RF_ReconDoneProc_t *));}int rf_ConfigureReconstruction(listp) RF_ShutdownList_t **listp;{ int rc; RF_FREELIST_CREATE(rf_recond_freelist, RF_MAX_FREE_RECOND, RF_RECOND_INC, sizeof(RF_RaidReconDesc_t)); if (rf_recond_freelist == NULL) return(ENOMEM); RF_FREELIST_CREATE(rf_rdp_freelist, RF_MAX_FREE_RDP, RF_RDP_INC, sizeof(RF_ReconDoneProc_t)); if (rf_rdp_freelist == NULL) { RF_FREELIST_DESTROY(rf_recond_freelist,next,(RF_RaidReconDesc_t *)); return(ENOMEM); } rc = rf_ShutdownCreate(listp, rf_ShutdownReconstruction, NULL); if (rc) { RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n", __FILE__, __LINE__, rc); rf_ShutdownReconstruction(NULL); return(rc); }#ifdef KERNEL if (!recon_thread_initialized) { RF_CREATE_THREAD(recon_thr_handle, rf_ReconKernelThread, NULL); recon_thread_initialized = 1; }#endif /* KERNEL */ return(0);}static RF_RaidReconDesc_t *AllocRaidReconDesc(raidPtr, row, col, spareDiskPtr, numDisksDone, srow, scol) RF_Raid_t *raidPtr; RF_RowCol_t row; RF_RowCol_t col; RF_RaidDisk_t *spareDiskPtr; int numDisksDone; RF_RowCol_t srow; RF_RowCol_t scol;{ RF_RaidReconDesc_t *reconDesc; RF_FREELIST_GET(rf_recond_freelist,reconDesc,next,(RF_RaidReconDesc_t *)); reconDesc->raidPtr = raidPtr; reconDesc->row = row; reconDesc->col = col; reconDesc->spareDiskPtr=spareDiskPtr; reconDesc->numDisksDone=numDisksDone; reconDesc->srow=srow; reconDesc->scol=scol; reconDesc->state = 0; reconDesc->next = NULL; return(reconDesc);}static void FreeReconDesc(reconDesc) RF_RaidReconDesc_t *reconDesc;{#if RF_RECON_STATS > 0 printf("RAIDframe: %lu recon event waits, %lu recon delays\n", reconDesc->numReconEventWaits, reconDesc->numReconExecDelays);#endif /* RF_RECON_STATS > 0 */#ifdef KERNEL printf("RAIDframe: %lu max exec ticks\n", reconDesc->maxReconExecTicks);#endif /* KERNEL */#if (RF_RECON_STATS > 0) || defined(KERNEL) printf("\n");#endif /* (RF_RECON_STATS > 0) || KERNEL */ RF_FREELIST_FREE(rf_recond_freelist,reconDesc,next);}/***************************************************************************************** * * primary routine to reconstruct a failed disk. This should be called from * within its own thread. It won't return until reconstruction completes, * fails, or is aborted. ****************************************************************************************/int rf_ReconstructFailedDisk(raidPtr, row, col) RF_Raid_t *raidPtr; RF_RowCol_t row; RF_RowCol_t col;{#ifdef SIMULATE RF_PendingRecon_t *pend; RF_RowCol_t r, c;#endif /* SIMULATE */ RF_LayoutSW_t *lp; int rc; lp = raidPtr->Layout.map; if (lp->SubmitReconBuffer) { /* * The current infrastructure only supports reconstructing one * disk at a time for each array. */#ifdef SIMULATE if (raidPtr->reconInProgress) { RF_Malloc(pend, sizeof(RF_PendingRecon_t), (RF_PendingRecon_t *)); pend->row = row; pend->col = col; pend->next = raidPtr->pendingRecon; raidPtr->pendingRecon = pend; /* defer until current recon completes */ return(0); } raidPtr->reconInProgress++;#else /* SIMULATE */ RF_LOCK_MUTEX(raidPtr->mutex); while (raidPtr->reconInProgress) { RF_WAIT_COND(raidPtr->waitForReconCond, raidPtr->mutex); } raidPtr->reconInProgress++; RF_UNLOCK_MUTEX(raidPtr->mutex);#endif /* SIMULATE */ rc = rf_ReconstructFailedDiskBasic(raidPtr, row, col); } else { RF_ERRORMSG1("RECON: no way to reconstruct failed disk for arch %c\n", lp->parityConfig); rc = EIO; }#ifdef SIMULATE pend = raidPtr->pendingRecon; if (pend) { /* launch next recon */ raidPtr->pendingRecon = pend->next; r = pend->row; c = pend->col; RF_Free(pend, sizeof(RF_PendingRecon_t)); return(rf_ReconstructFailedDisk(raidPtr, r, c)); }#else /* SIMULATE */ RF_LOCK_MUTEX(raidPtr->mutex); raidPtr->reconInProgress--; RF_UNLOCK_MUTEX(raidPtr->mutex); RF_SIGNAL_COND(raidPtr->waitForReconCond);#endif /* SIMULATE */ return(rc);}int rf_ReconstructFailedDiskBasic(raidPtr, row, col) RF_Raid_t *raidPtr; RF_RowCol_t row; RF_RowCol_t col;{ RF_RaidDisk_t *spareDiskPtr = NULL; RF_RaidReconDesc_t *reconDesc; RF_RowCol_t srow, scol; int numDisksDone, rc; /* first look for a spare drive onto which to reconstruct the data */ /* spare disk descriptors are stored in row 0. This may have to change eventually */ RF_LOCK_MUTEX(raidPtr->mutex); RF_ASSERT (raidPtr->Disks[row][col].status == rf_ds_failed); if (raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE) { if (raidPtr->status[row] != rf_rs_degraded) { RF_ERRORMSG2("Unable to reconstruct disk at row %d col %d because status not degraded\n",row,col); RF_UNLOCK_MUTEX(raidPtr->mutex); return(EINVAL); } srow = row; scol = (-1); } else { srow = 0; for (scol=raidPtr->numCol; scol<raidPtr->numCol + raidPtr->numSpare; scol++) { if (raidPtr->Disks[srow][scol].status == rf_ds_spare) { spareDiskPtr = &raidPtr->Disks[srow][scol]; spareDiskPtr->status = rf_ds_used_spare; break; } } if (!spareDiskPtr) { RF_ERRORMSG2("Unable to reconstruct disk at row %d col %d because no spares are available\n",row,col); RF_UNLOCK_MUTEX(raidPtr->mutex); return(ENOSPC); }#if RF_DEMO > 0 if (!rf_demoMode) {#endif /* RF_DEMO > 0 */ printf("RECON: initiating reconstruction on row %d col %d -> spare at row %d col %d\n",row, col, srow, scol);#if RF_DEMO > 0 }#endif /* RF_DEMO > 0 */ } RF_UNLOCK_MUTEX(raidPtr->mutex); reconDesc = AllocRaidReconDesc((void *) raidPtr, row, col,spareDiskPtr, numDisksDone, srow , scol); raidPtr->reconDesc = (void *) reconDesc;#if RF_RECON_STATS > 0 reconDesc->hsStallCount = 0; reconDesc->numReconExecDelays = 0; reconDesc->numReconEventWaits = 0;#endif /* RF_RECON_STATS > 0 */#ifdef KERNEL reconDesc->reconExecTimerRunning = 0; reconDesc->reconExecTicks = 0; reconDesc->maxReconExecTicks = 0;#endif /* KERNEL */#if RF_DEMO > 0 && !defined(SIMULATE) if (rf_demoMode) { char cbuf[10]; printf("About to start reconstruction, hit return to continue:"); gets(cbuf); }#endif /* RF_DEMO > 0 && !SIMULATE */ rc = rf_ContinueReconstructFailedDisk(reconDesc); return(rc);}int rf_ContinueReconstructFailedDisk(reconDesc) RF_RaidReconDesc_t *reconDesc;{ RF_Raid_t *raidPtr=reconDesc->raidPtr; RF_RowCol_t row=reconDesc->row; RF_RowCol_t col=reconDesc->col; RF_RowCol_t srow=reconDesc->srow; RF_RowCol_t scol=reconDesc->scol; RF_ReconMap_t *mapPtr; RF_ReconEvent_t *event; struct timeval etime, elpsd; unsigned long xor_s, xor_resid_us; int retcode,i, ds; switch (reconDesc->state) { case 0: raidPtr->accumXorTimeUs = 0; /* create one trace record per physical disk */ RF_Malloc(raidPtr->recon_tracerecs, raidPtr->numCol * sizeof(RF_AccTraceEntry_t), (RF_AccTraceEntry_t *)); /* quiesce the array prior to starting recon. this is needed to assure no nasty interactions * with pending user writes. We need to do this before we change the disk or row status. */ reconDesc->state=1; Dprintf("RECON: begin request suspend\n"); retcode = rf_SuspendNewRequestsAndWait(raidPtr); Dprintf("RECON: end request suspend\n"); rf_StartUserStats(raidPtr); /* zero out the stats kept on user accs */#ifdef SIMULATE if (retcode) return(0);#endif /* SIMULATE */ /* fall through to state 1 */ case 1: RF_LOCK_MUTEX(raidPtr->mutex); /* create the reconstruction control pointer and install it in the right slot */ raidPtr->reconControl[row] = rf_MakeReconControl(reconDesc, row, col, srow, scol); mapPtr=raidPtr->reconControl[row]->reconMap; raidPtr->status[row] = rf_rs_reconstructing; raidPtr->Disks[row][col].status = rf_ds_reconstructing;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -