--- ./source/private_module/enterprise/event/rephc_event.c	2018-04-27 10:16:51.000000000 +0000
+++ ./source/private_module/enterprise/event/rephc_event.c.hotpatch	2021-01-20 08:28:39.000000000 +0000
@@ -18129,7 +18129,7 @@
 
     return;
 }
-
+extern void recordPairStatInfoRepHc(uint32_t localPairId, uint64_t localDelay, uint64_t rmtDelay, uint64_t ioCount);
 /**********************************************************************
 *     : ļ˫ƷIO ERR¼
 * :
@@ -18157,7 +18157,6 @@
         DBG_LogError(REPHC_LOG_ID_NEW, "Local pair id is invalid %u.", localId);
         return;
     }
-
     getRepHcPairStatus(localId, &pairStatus);
     if (REPHC_PAIR_STATE_NORMAL != pairStatus)
     {
@@ -18166,7 +18165,8 @@
             localId, pairStatus);
         return;
     }
-
+	recordPairStatInfoRepHc(localId, wDealyStat->totalLocalDelay,
+                                    wDealyStat->totalRemoteDelay, wDealyStat->ioCount);
     isNeedIso = setAndCheckPairNeedIsoRepHc(localId, wDealyStat->totalLocalDelay,
         wDealyStat->totalRemoteDelay, wDealyStat->ioCount, &isoType);
     if ((FALSE == isNeedIso) || (REPHC_ISO_BUTT == isoType))
--- ./source/private_module/enterprise/event/v3/rephc_fs_event.c	2018-04-27 10:16:51.000000000 +0000
+++ ./source/private_module/enterprise/event/v3/rephc_fs_event.c.hotpatch	2021-01-20 08:28:39.000000000 +0000
@@ -5462,11 +5462,11 @@
         callback(context, RETURN_ERROR, REPHC_ARB_STATUS_UNKNOWN);
         return;
     }
-    
+    /* ļϵͳҪԼʱ˽ӹҵ񳡾ԣԣû˫ĳصֱcallback winΪUNKNOWN */
     if (!isHM)
     {
         DBG_LogDebug(REPHC_LOG_ID_NEW, "Rephc not found in fsId(%u).", fsId);
-        callback(context, RETURN_OK, REPHC_ARB_STATUS_WIN);
+        callback(context, RETURN_OK, REPHC_ARB_STATUS_UNKNOWN);
         return;
     }
 
@@ -5605,5 +5605,298 @@
     
     return RETURN_OK;
 }
+/******************************************************************************
+*    ܣ spaceϱıioerrorתԶioerror
+*:  ioErrEvt     : ioerrorݽṹ
+            localPairId  : ҪfsId
+* 
+*  ֵ 
+*ע 
+*************************************************************************/
+void handleSpcLockTimeOutEvent(uint32_t localPairId, 
+                                void (*callback)(void* context, int32_t result), 
+                                void* context)
+{
+    REPHC_FS_IO_ERR_PARA_S fsPara = {0};
+    fsPara.isParse = FALSE;
+    fsPara.isTempError = FALSE;
+    
+    handleRepHcFsIoErrorEvt(localPairId, RETURN_OK, RETURN_ERROR, 
+                            callback, context, &fsPara);
+    return;                        
+}
+
+/**********************************************************************
+*     : ˫spcʱ¼ص
+* : context ִ result ִн
+* : 
+*   ֵ: 
+* ע: 
+**********************************************************************/
+void handleSpcLockTimeOutEventCb(void* context, int32_t result)
+{
+    REPHC_FS_IO_ERR_S* ioErrEvt = NULL;
+
+    ioErrEvt = (REPHC_FS_IO_ERR_S *)context;
+    
+    DBG_LogInfo(REPHC_LOG_ID_NEW, 
+             "Handle spc lock timeout event finish, fs id(%u), result(%u).", ioErrEvt->fsId, result);
+
+    return;
+}
+
+/**********************************************************************
+*     : ȡspaceioerrorתԶioerror
+* :
+* : 
+*   ֵ: 
+* ע: úpair spinlock
+**********************************************************************/
+int32_t getSpaceTimeoutRephcIOStatCycle(REPHC_PAIR_INFO_S* pairInfo, int32_t *conCycle)
+{
+    int32_t cycle = 0;
+    uint32_t remain = 0;
+
+    if (pairInfo->cfgInfo.arrayIsoCycle < REPHC_MIN_ISO_CYCLE_LEN 
+        || pairInfo->cfgInfo.arrayIsoCycle > REPHC_MAX_ISO_CYCLE_LEN)
+    {
+        DBG_LogError(REPHC_LOG_ID_NEW, 
+            "arrayIsoCycle(%u) is invalid.", pairInfo->cfgInfo.arrayIsoCycle);
+        return RETURN_ERROR;
+    }
+    cycle = 30 / pairInfo->cfgInfo.arrayIsoCycle;
+    remain = 30 % pairInfo->cfgInfo.arrayIsoCycle;
+    /* 
+      IOոϱ˫,30ʱ,ȡڸͳֵ
+      ʱ+1
+    */
+    cycle = (remain != 0) ? (cycle + 1) : cycle;
+
+    *conCycle = cycle;
+    return RETURN_OK;
+}
+
+/**********************************************************************
+*     : ǷлspaceioerrorΪԶioerror
+* :
+* : 
+*   ֵ: 
+* ע: 
+**********************************************************************/
+bool isSpaceTimeoutCausedByRmt(uint32_t localPairId)
+{
+    REPHC_PAIR_INFO_S*  pairInfo = NULL;
+    REPHC_PAIR_RUN_S* runInfo = NULL;
+    uint8_t curIndex = 0;
+    int32_t cycle;
+    uint64_t avgDiff;
+    int ret;
+    
+    spin_lock(&g_repHcPairCtrl.pairLock);
+    /* ȡpair Info*/
+    pairInfo = getRepHcPairWithNoLock(localPairId);
+    if (NULL == pairInfo)
+    {
+        spin_unlock(&g_repHcPairCtrl.pairLock);
+        DBG_LogError(REPHC_LOG_ID_NEW, 
+            "Fail to get pair(%u) when set array iso switch.", localPairId);
+        return FALSE;
+    }
+    ret = getSpaceTimeoutRephcIOStatCycle(pairInfo, &cycle);
+    if (RETURN_OK != ret)
+    {
+        spin_unlock(&g_repHcPairCtrl.pairLock);
+        return FALSE;
+    }
+    
+    runInfo = &pairInfo->runInfo;
+    curIndex = runInfo->curIndex;
+    do{
+        curIndex = (curIndex == 0) ? (REPHC_MAX_HIS_STAT_INFO_NUM - 1) : (curIndex - 1);
+        if (INVALID_VALUE64 == runInfo->statInfo[curIndex].localAvgDelay 
+                || INVALID_VALUE64 == runInfo->statInfo[curIndex].rmtAvgDelay)
+        {
+            spin_unlock(&g_repHcPairCtrl.pairLock);
+            return FALSE;
+        }
+
+        DBG_LogDebug(REPHC_LOG_ID_NEW, 
+                "Current cycle info(localid %u, curIndex %u, localAvgDelay %llu, rmtAvgDelay %llu, cycle %u).", 
+                localPairId, curIndex, runInfo->statInfo[curIndex].localAvgDelay,
+                runInfo->statInfo[curIndex].rmtAvgDelay, cycle);
+                
+        if (runInfo->statInfo[curIndex].rmtAvgDelay < runInfo->statInfo[curIndex].localAvgDelay)
+        {
+            spin_unlock(&g_repHcPairCtrl.pairLock);
+            return FALSE;
+        }
+        
+        
+        avgDiff = runInfo->statInfo[curIndex].rmtAvgDelay - runInfo->statInfo[curIndex].localAvgDelay;
+        if (avgDiff < 100)
+        {
+            spin_unlock(&g_repHcPairCtrl.pairLock);
+            return FALSE;
+        }
+        
+        /* cycleӶƽʱӱƽʱӴ 100msл */
+        cycle--;
+    } while(cycle > 0);
+    
+    
+    DBG_LogInfo(REPHC_LOG_ID_NEW, 
+                "Need change timeout to remote ioerror(localid %u).", localPairId);
+
+
+    spin_unlock(&g_repHcPairCtrl.pairLock);
+
+    return TRUE;
+}
+
+void startSpcLockTimeOutEvent(REPHC_FS_IO_ERR_S* ioErrEvt)
+{
+    uint32_t localPairId = INVALID_VALUE32;
+    bool isCausedByRmt = FALSE;
+
+    /* ʱɱ(ͳʱӱԶʱӴ),ͨpalϱл,ڼʱ*/
+    localPairId = getRepHcLocalPairIdByDsIdFast(ioErrEvt->fsId);
+    isCausedByRmt = isSpaceTimeoutCausedByRmt(localPairId);
+    if (FALSE == isCausedByRmt)
+    {
+        DBG_LogInfo(REPHC_LOG_ID_NEW, "Timeout enabled, no need interrupt, fsId %u, isCausedByRmt %u.",
+                        ioErrEvt->fsId, isCausedByRmt);
+        releaseRepHcIoErrEvt(ioErrEvt);
+        return;
+    }
+    
+    handleSpcLockTimeOutEvent(localPairId, handleSpcLockTimeOutEventCb, (void *)ioErrEvt);
+    
+    return;
+}
+
+void iodHandleRepHcFsIoTimeoutEvent(void* data)
+{
+    REPHC_FS_IO_ERR_S* ioErrEvt = NULL;
+
+    ioErrEvt = (REPHC_FS_IO_ERR_S*)data;
+    startSpcLockTimeOutEvent(ioErrEvt);
+    return;
+}
+
+
+int32_t rephcHandleFsIoTimeOut(uint32_t fsId)
+{
+    REPHC_FS_IO_ERR_S* ioErrEvt = NULL;
+    int32_t ret = RETURN_ERROR;
+    uint32_t vStoreId = INVALID_VALUE32;
+
+    ioErrEvt = applyIoErrRepHcEvt();
+    if (NULL == ioErrEvt)
+    {
+        DBG_LogError(REPHC_LOG_ID_NEW,
+            "Get free io err event info node failed,(fsId %u).", fsId);
+        return REPHC_ARB_STATUS_UNKNOWN;
+    }
+    
+    ret = getFsVstoreIdIntf(fsId, &vStoreId);
+    if (RETURN_OK != ret)
+    {
+        DBG_LogError(REPHC_LOG_ID_NEW, "Get fs(%u) vstor failed.", fsId);
+        releaseRepHcIoErrEvt(ioErrEvt);
+        return REPHC_ARB_STATUS_UNKNOWN;
+    }
+    ioErrEvt->fsId = fsId;    
+    ioErrEvt->arbResult = REPHC_ARB_STATUS_UNKNOWN;
+    ioErrEvt->vStoreId = vStoreId;
+    ioErrEvt->retryStartTime = INVALID_VALUE64;
+        
+    ret = iodDelayHandleRepHcEvent((void*)ioErrEvt, iodHandleRepHcFsIoTimeoutEvent, 0,
+                    FALSE);
+    if (RETURN_OK != ret)
+    {
+        DBG_LogError(REPHC_LOG_ID_NEW,
+                     "Start handle fs ioerror event(fsid %u, vStoreId %u) failed.",
+                     fsId, vStoreId);
+        releaseRepHcIoErrEvt(ioErrEvt);
+        return REPHC_ARB_STATUS_UNKNOWN;
+    }
+    
+    return RETURN_OK;
+}
+
+/**********************************************************************
+*     : SPACE ʱ¼
+* : fsId
+* : 
+*   ֵ: 
+* ע: 
+**********************************************************************/
+int32_t notifyHmTimeoutHandle(uint32_t fsId)
+{
+    int32_t ret = RETURN_ERROR;
+    bool isHM = FALSE;
+
+    DBG_LogInfo(REPHC_LOG_ID_NEW, "Receive lock timeout event, fsId(%u).", fsId);
+
+    if (INVALID_VALUE32 == fsId || isOnlineUpdating())
+    {
+        DBG_LogInfo(REPHC_LOG_ID_NEW, "Fs id is null, fs id(%u).", fsId);
+        return REPHC_ARB_STATUS_UNKNOWN;
+    }
+
+    /* жļϵͳû˫ */
+    ret = getHyperMetroStateIntf(fsId, &isHM);
+    if (RETURN_OK != ret)
+    {
+        return REPHC_ARB_STATUS_UNKNOWN;
+    }
+    
+    if (!isHM)
+    {
+        DBG_LogDebug(REPHC_LOG_ID_NEW, "Rephc not found in fsId(%u).", fsId);
+        return REPHC_ARB_STATUS_UNKNOWN;
+    }
+
+    ret = rephcHandleFsIoTimeOut(fsId);
+    if (RETURN_OK != ret)
+    {
+        return REPHC_ARB_STATUS_UNKNOWN;
+    }
+    
+    return RETURN_OK;
+}
+
+/**********************************************************************
+*     : ȡ˫IOʱĽ
+* : fsId
+* : 
+*   ֵ: return_ok: ɣٲ״̬unknown
+            return_error:ûдɣٲ״̬unknown
+* ע: 
+**********************************************************************/
+int32_t getHmTimeoutHandleResult(uint32_t fsId, int32_t *arbResult)
+{
+    uint32_t localPairId = INVALID_VALUE32;
+    uint8_t tmpArbResult = INVALID_VALUE8;
+    
+    localPairId = getRepHcLocalPairIdByDsIdFast(fsId);
+    getRepHcArbResult(localPairId, &tmpArbResult);
+
+    if (NULL != arbResult)
+    {
+        *arbResult = tmpArbResult;
+    }
+
+    if (REPHC_ARB_STATUS_UNKNOWN == tmpArbResult)
+    {
+        return RETURN_ERROR;
+    }
+
+    return RETURN_OK;
+}
+
+
+EXPORT_SYMBOL(notifyHmTimeoutHandle);
+EXPORT_SYMBOL(getHmTimeoutHandleResult);
 
 
--- ./source/private_module/enterprise/pair/v3/rephc_pair.c	2018-04-28 09:18:54.000000000 +0000
+++ ./source/private_module/enterprise/pair/v3/rephc_pair.c.hotpatch	2021-01-20 08:28:39.000000000 +0000
@@ -1407,7 +1407,7 @@
     {
         DBG_LogDebug(REPHC_LOG_ID_NEW, 
             "No io white this cycle(localid %u).", localPairId);
-        clearStatInfoRepHc(pairInfo);
+
         pairInfo->runInfo.contiIsoCycleNum = 0;
         pairInfo->runInfo.isoType = REPHC_ISO_BUTT;
         spin_unlock(&g_repHcPairCtrl.pairLock);
@@ -1437,7 +1437,7 @@
             "conticycle num %u).", 
             localPairId, avgDelayDiff, pairInfo->cfgInfo.arrayIsoValue,
             pairInfo->runInfo.contiIsoCycleNum);
-        clearStatInfoRepHc(pairInfo);
+
         pairInfo->runInfo.contiIsoCycleNum = 0;
         pairInfo->runInfo.isoType = REPHC_ISO_BUTT;
         spin_unlock(&g_repHcPairCtrl.pairLock);
@@ -1450,7 +1450,7 @@
     if (isLocalDelay == isLastLocalIso)
     {
         pairInfo->runInfo.contiIsoCycleNum++;
-        recordStatInfoRepHc(pairInfo, lAvgDelay, rAvgDelay, ioCount);
+
         if (pairInfo->runInfo.maxIsoCycleNum <= pairInfo->runInfo.contiIsoCycleNum)
         {
             pairInfo->runInfo.maxIsoCycleNum = pairInfo->runInfo.contiIsoCycleNum;
@@ -1459,7 +1459,7 @@
     }
     else
     {
-        clearStatInfoRepHc(pairInfo);
+
         pairInfo->runInfo.contiIsoCycleNum = 0;
         pairInfo->runInfo.isoType = REPHC_ISO_BUTT;
         spin_unlock(&g_repHcPairCtrl.pairLock);
@@ -10183,3 +10183,51 @@
     return;
 }
 
+/**********************************************************************
+*     : ¼pairͳϢ
+* : localPairId localId
+            localDelay ʱ
+            rmtDelay   Զʱ
+            ioCount    io
+* : 
+*   ֵ: 
+* ע:
+**********************************************************************/
+void recordPairStatInfoRepHc(uint32_t localPairId, uint64_t localDelay,
+                             uint64_t rmtDelay, uint64_t ioCount)
+{
+    uint64_t lAvgDelay = 0;
+    uint64_t rAvgDelay = 0;
+    REPHC_PAIR_INFO_S*  pairInfo = NULL;
+
+    spin_lock(&g_repHcPairCtrl.pairLock);
+    /* ȡpair Info*/
+    pairInfo = getRepHcPairWithNoLock(localPairId);
+    if (NULL == pairInfo)
+    {
+        spin_unlock(&g_repHcPairCtrl.pairLock);
+        DBG_LogError(REPHC_LOG_ID_NEW, 
+            "Fail to get pair(%u) when set array iso switch.", localPairId);
+        return;
+    }
+
+    if (0 == ioCount)
+    {
+        DBG_LogDebug(REPHC_LOG_ID_NEW, 
+            "No io white this cycle(localid %u).", localPairId);
+        clearStatInfoRepHc(pairInfo);
+        spin_unlock(&g_repHcPairCtrl.pairLock);
+        return;
+    }
+    
+    lAvgDelay = localDelay / ioCount;
+    rAvgDelay = rmtDelay / ioCount;
+    /* ¼ʱͳϢ */
+    recordStatInfoRepHc(pairInfo, lAvgDelay, rAvgDelay, ioCount);
+    
+    spin_unlock(&g_repHcPairCtrl.pairLock);
+
+    return;
+}
+
+
--- ./source/private_module/enterprise/task/v3/rephc_fs_action.c	2018-04-28 09:18:54.000000000 +0000
+++ ./source/private_module/enterprise/task/v3/rephc_fs_action.c.hotpatch	2021-01-20 08:28:39.000000000 +0000
@@ -1884,9 +1884,9 @@
     int32_t result = RETURN_ERROR;
     
     commPara = getRepHcTaskPriPara(taskHead);
-
     if (RETURN_OK == commPara->result)
     {
+        setRepHcArbResult(commPara->localPairId, commPara->localArbRet);
         SET_TASK_RET(taskHead, RSS_ACTION_RESULT_OK, RETURN_OK);
         return RSS_ACTION_TYPE_SYNC;
     }
