RF_CREATE_THREAD(recon_thr_handle, rf_ReconKernelThread, NULL);
RF_CREATE_THREAD(recon_thr_handle, rf_ReconKernelThread, NULL, "raid_recon");
RF_RaidReconDesc_t *rf_AllocRaidReconDesc __P((RF_Raid_t *, RF_RowCol_t, RF_RowCol_t, RF_RaidDisk_t *, int, RF_RowCol_t, RF_RowCol_t));int rf_ProcessReconEvent __P((RF_Raid_t *, RF_RowCol_t, RF_ReconEvent_t *));int rf_IssueNextReadRequest __P((RF_Raid_t *, RF_RowCol_t, RF_RowCol_t));int rf_TryToRead __P((RF_Raid_t *, RF_RowCol_t, RF_RowCol_t));int rf_ComputePSDiskOffsets __P((RF_Raid_t *, RF_StripeNum_t, RF_RowCol_t, RF_RowCol_t, RF_SectorNum_t *, RF_SectorNum_t *, RF_RowCol_t *, RF_RowCol_t *, RF_SectorNum_t *));int rf_ReconReadDoneProc(void *, int);int rf_ReconWriteDoneProc(void *, int);void rf_CheckForNewMinHeadSep(RF_Raid_t *, RF_RowCol_t, RF_HeadSepLimit_t);int rf_CheckHeadSeparation(RF_Raid_t *, RF_PerDiskReconCtrl_t *, RF_RowCol_t, RF_RowCol_t, RF_HeadSepLimit_t, RF_ReconUnitNum_t);void rf_ForceReconReadDoneProc __P((void *, int));void rf_ShutdownReconstruction __P((void *));/* * these functions are inlined on gcc. If they are used more than * once, it is strongly advised to un-line them */INTEGRATE void rf_FreeReconDesc __P((RF_RaidReconDesc_t *));INTEGRATE int rf_IssueNextWriteRequest __P((RF_Raid_t *, RF_RowCol_t));INTEGRATE int rf_CheckForcedOrBlockedReconstruction __P((RF_Raid_t *, RF_ReconParityStripeStatus_t *, RF_PerDiskReconCtrl_t *, RF_RowCol_t, RF_RowCol_t, RF_StripeNum_t, RF_ReconUnitNum_t));INTEGRATE void rf_SignalReconDone __P((RF_Raid_t *));/* XXX these should be in a .h file somewhere */int raidlookup __P((char *, struct proc *, struct vnode **));int raidwrite_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);int raidread_component_label(dev_t, struct vnode *, RF_ComponentLabel_t *);struct RF_ReconDoneProc_s {	void    (*proc) (RF_Raid_t *, void *);	void   *arg;	RF_ReconDoneProc_t *next;};static RF_FreeList_t *rf_rdp_freelist;#define RF_MAX_FREE_RDP 4#define RF_RDP_INC      1INTEGRATE void rf_SignalReconDone(RF_Raid_t * raidPtr){	RF_ReconDoneProc_t *p;	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) (RF_Raid_t *, void *),    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. * ****************************************************************************************/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);	}	if (!recon_thread_initialized) {		RF_CREATE_THREAD(recon_thr_handle, rf_ReconKernelThread, NULL);		recon_thread_initialized = 1;	}	return (0);}RF_RaidReconDesc_t *rf_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);}