--- ./source/private_module/pmgr/pmgr_intf.c	2018-04-20 08:53:49.000000000 +0000
+++ ./source/private_module/pmgr/pmgr_intf.c.hotpatch	2020-04-17 12:52:21.000000000 +0000
@@ -84,13 +84,13 @@
     return RETURN_OK;
 }
 
-/**************************************************************************
-     :  diskpoolԪݶ
- :  diskPoolCfgPara         DiskPoolϢṹ
- :  
- ֵ  :  ִгɹRETURN_OKִʧܷRETURN_ERROR         
-     :  
-**************************************************************************/
+void fillAddDiskToPoolTaskStepEx(poolid_t poolId, TASK_S *task);
+void replaceDiskSetTaskPause(PMGR_EH_TASK *ehTask);
+extern void deleteDiskOutTimer(poolid_t poolId, diskid_t diskId);
+extern void setTaskSchedulePauseTime(poolid_t poolId, uint32_t tierId, uint32_t pauseTime);
+
+    
+
 int32_t createPoolMobj(CFG_DISK_POOL_PARA_S *diskPoolCfgPara)
 {
     int32_t ret;
@@ -3637,7 +3637,7 @@
         {
             continue;
         }
-
+        setTaskSchedulePauseTime(poolId, index, 0);  /* ʱͣ */
         /*  */
         handleExpand(poolId, index, handleExpandCallback, ehTask);
     }  
@@ -4182,10 +4182,10 @@
     ehTask->poolId          = poolId;
     ehTask->objList         = diskList;
     ehTask->objNum          = diskNum;
-    /* modified by h90006795 for DTS2013120410988 , 2014-04-21 begin */ 
     ehTask->diskId          = replaceDiskId;
-    /* modified by h90006795 for DTS2013120410988 , 2014-04-21 end */ 
-    fillAddDiskToPoolTaskStep(poolId, (TASK_S *)ehTask);
+    ehTask->pad2            = TRUE;   /* жͬλ̽볡Ҫͣȼ񣬽ñΪFALSE */
+    replaceDiskSetTaskPause(ehTask);  /* жͬλ̽볡̼뵽ѡм䣬ȼͣͣ */
+    fillAddDiskToPoolTaskStepEx(poolId, (TASK_S *)ehTask);
 
     TASK_CALL_ACTION_START_ASYNC((TASK_S *)ehTask);
 
@@ -8097,3 +8097,103 @@
     }
     return;
 }
+
+void fillAddDiskToPoolTaskStepEx(poolid_t poolId, TASK_S *task)
+{
+    uint32_t idx = 0;
+
+    task->ActionArray[idx++] = PMGR_ADD_DISK_TO_POOL_TASK_OVER;
+    task->ActionArray[idx++] = PMGR_GET_TASK_TO_PAUSE;
+    task->ActionArray[idx++] = PMGR_CREATE_DISK_MOBJ_BY_SPA;
+    task->ActionArray[idx++] = PMGR_ADD_DISK_TO_LOCAL_LSIT;
+
+    if (hasMemberDiskConfigCompleted(poolId))
+    {
+        task->ActionArray[idx++] = PMGR_INIT_DISK_MOBJ_BY_SPA;
+        task->ActionArray[idx++] = PMGR_SET_DG_ID_OF_NEW_ADD_DISK;
+
+        task->ActionArray[idx++] = PMGR_SET_POOL_DISK_CONFIG_COMPLETE;
+
+        task->ActionArray[idx++] = PMGR_SYNC_DISK_INFO;
+        task->ActionArray[idx++] = PMGR_SYNC_DG_INFO;
+    }
+
+    task->ActionArray[idx++] = ACTION_OPCODE_BUTT;
+
+    return;
+}
+
+/**************************************************************************
+    :  ͬλ̣̽ͣǰ㼶ȼ񣬲ͣǰ㼶ȱ
+:  ehTask - 
+:  
+ֵ  :  
+    :  
+**************************************************************************/
+void replaceDiskSetTaskPause(PMGR_EH_TASK *ehTask)
+{
+    uint64_t taskId;
+    TASK_RECORD_S *taskRcd = NULL;
+    tierid_t tierId;
+    poolid_t poolId;
+    diskid_t replaceDiskId;
+
+    poolId = ehTask->poolId;
+    replaceDiskId = ehTask->diskId;
+
+    /** 
+        ͬλ̴̣̽ȫعʱҪͬ㼶ȼ͵ͣС̳
+        ع̷ȱCKعʱֲȱCK
+    **/
+    if (INVALID_DISK_ID != replaceDiskId)
+    { 
+        taskId              = GEN_RECON_TASK_ID(DISK_RECON, replaceDiskId);
+        taskRcd             = getTaskRcdFromTaskList(taskId);
+        ehTask->taskRcd     = taskRcd;
+
+        tierId = queryTierIdByDiskIdIntf(replaceDiskId);
+        /* 
+            tierIdЧ̴عʱ
+            1ͣͬ㼶ȼ
+            2ͬ㼶ȼӲͣ
+        */
+        if (tierId < TIER_TYPE_BUTT && NULL != taskRcd && isReconNoSpace(poolId, replaceDiskId))
+        {
+            setTaskSchedulePauseTime(poolId, tierId, 1);
+            ehTask->pad2    = FALSE;
+        }
+    }
+}
+
+/**************************************************************************
+    :  ȡָӲ̵عʱ״̬Ϊwait
+:  poolId - ӲID
+           diskId - Ӳ߼ID
+:  
+ֵ  :  
+    :  
+**************************************************************************/
+void cancelDiskReconTaskDelayIntf(poolid_t poolId, diskid_t diskId)
+{
+    if (!isPoolWorkNode(poolId))
+    {
+        return;
+    }
+
+    if (INPUT_DISK_INVALID(diskId))
+    {
+        DBG_LogWarning(NO_LOGID, "Cancel delay disk recon task failed, disk id(%u) is invalid of pool(%u).", diskId, poolId);
+        return;
+    }
+
+    DBG_LogInfo(NO_LOGID, "Disk replace begin delete old disk(%u) of pool(%u) out timer " 
+                      "and set disk recon task status to wait.", diskId, poolId);
+    
+    deleteDiskOutTimer(poolId, diskId);
+    setDiskReconTaskToWait(diskId);
+
+    return;
+}
+EXPORT_SYMBOL(cancelDiskReconTaskDelayIntf);
+
+
--- ./source/private_module/pmgr/pmgr_task_mgr.c	2018-02-09 13:47:03.000000000 +0000
+++ ./source/private_module/pmgr/pmgr_task_mgr.c.hotpatch	2020-04-18 02:47:21.000000000 +0000
@@ -38,8 +38,8 @@
 #include "pmgr_tlvmsg.h"
 
 /*****************************************************************/
-
-/* ִе */
+#define MAX_TASK_SCHEDULE_PAUSE_TIME  (2)
+uint32_t g_taskSchedulePauseTime[MAX_POOL_NUM][TIER_TYPE_BUTT] = {{0}};
 spinlock_t g_runningTaskRcdListLock;
 
 /* ִе */
@@ -93,7 +93,7 @@
 /* ϵͳĺ̨ */
 uint32_t g_MaxTaskNum;
 /*****************************************************************/
-
+void getDiskCanRwNumInDg(PMGR_OBJ_S *poolObj, diskid_t selfDiskId, dgid_t dgId, uint32_t *diskCanRwNumInDg, uint32_t *diskTotalNumInDg);
 /**************************************************************************
     :  ϱص־
 :  poolId   POOL
@@ -1941,7 +1941,7 @@
         return FALSE;
     }   
 }
-
+uint32_t isTaskScheduleCanStart(poolid_t poolId, uint8_t tierId);
 /*******************************************************************************
      :  жϵǰܷ
  :  newTaskRcd ָǰָ 
@@ -1955,8 +1955,6 @@
     uint32_t tierState;
     PMGR_OBJ_S *poolObj = NULL;
     uint32_t tierId;
-    /* modified by w90005868 for DTS2014080107868,DTS2014080505534, 2014-08-01 begin */
-
     poolObj = getPoolObj(newTaskRcd->poolId);
     /* ϵͳУ */
     if (TRUE == (bool)UPGRADE_GetAllUpgradeFlag())
@@ -1965,8 +1963,11 @@
                             DBG_LOG_INFO, PMGR_LOG_ID0719, "Sys is online upgrading, can not start new task.");
         return FALSE;
     }
-    /* modified by w90005868 for DTS2014080107868,DTS2014080505534, 2014-08-01 end */
-
+    if (!isTaskScheduleCanStart(newTaskRcd->poolId, newTaskRcd->tierId)) /* ݱжǷҪͣ */
+    {
+        DBG_LogInfo(NO_LOGID, "There is a new disk being replaced in pool(%d), disk(%d) can not start task(%u).", newTaskRcd->poolId, newTaskRcd->diskId, newTaskRcd->taskType);
+        return FALSE;
+    }
     spin_lock(&poolObj->poolObjLock);
     if ((newTaskRcd->poolId != poolObj->diskPoolCfgPara.diskPoolId) || (!poolObj->backGroundFlag))
     {
@@ -1979,7 +1980,6 @@
     {
         return FALSE;
     }
-
     if (LEVELING == newTaskRcd->taskType)
     {
         tierId = newTaskRcd->tierId;
@@ -2660,20 +2660,20 @@
     
     ehTask = (PMGR_EH_TASK *)task;
     newTaskRcd = ehTask->taskRcd;
-    
+    if (TRUE == ehTask->pad2) 
+    {
+        TASK_CALL_ACTION_DONE_ASYNC_WITH_RESULT(task, RETURN_OK);  
+        return RETURN_OK; 
+    }
+       
     if (NULL == newTaskRcd)
     {
-        DBG_LogDebug(PMGR_LOG_ID3185, "The new task record is NULL.");
-        
+        DBG_LogDebug(PMGR_LOG_ID3185, "The new task record is NULL.");       
         SET_GOTO_TASK_OVER_FLAG(task, TRUE);
         TASK_CALL_ACTION_DONE_ASYNC_WITH_RESULT(task, RETURN_OK);            
         return RETURN_OK;
     }
-
-    /* ǰٲҪִͣе */
     taskToPause = getOldTaskToPause(newTaskRcd);
-
-    /* ûִеҪֱͣһ */
     if (NULL == taskToPause)
     {
         DBG_LogInfo(PMGR_LOG_ID3186, "There is no task need to pause.");
@@ -3238,7 +3238,7 @@
 void forceReconFailProc(TASK_RECORD_S *taskRcd)
 {
     uint8_t isForceReconFail = FALSE;
-    uint32_t normalDiskNumInDg, diskNumInDg;
+    uint32_t diskCanRwNumInDg, diskTotalNumInDg;
     PMGR_OBJ_S *poolObj = NULL;
     struct list_head *pos = NULL;
     struct list_head *n = NULL;
@@ -3256,7 +3256,7 @@
     spin_lock(&poolObj->poolObjLock);
 
     /* ȡDG */
-    getNormalDiskNumInDg(poolObj, taskRcd->dgId, &normalDiskNumInDg, &diskNumInDg);
+    getDiskCanRwNumInDg(poolObj, taskRcd->diskId, taskRcd->dgId, &diskCanRwNumInDg, &diskTotalNumInDg);
 
     zoneTierType = taskRcd->tierId;
     /*DTS2015030407203 ǷZONEĳԱСڵDG,
@@ -3281,8 +3281,8 @@
         raidMemberDiskNum = (raidMemberDiskNum < RAID1_MEMBERDISK_NUMBER ?
                             RAID1_MEMBERDISK_NUMBER:raidMemberDiskNum);
 
-        if ((raidMemberDiskNum <= diskNumInDg) &&
-            (raidMemberDiskNum > normalDiskNumInDg))
+        if ((raidMemberDiskNum <= diskTotalNumInDg) &&
+            (raidMemberDiskNum > diskCanRwNumInDg))
         {
           
             isForceReconFail = TRUE;
@@ -3294,7 +3294,7 @@
     if (!isZoneInTier)
     {
         raidMemberDiskNum = RAID1_MEMBERDISK_NUMBER;
-        if (raidMemberDiskNum > normalDiskNumInDg)
+        if (raidMemberDiskNum > diskCanRwNumInDg)
         {
 
             isForceReconFail = TRUE;
@@ -3306,9 +3306,9 @@
     
     if (isForceReconFail)
     {
-        DBG_LogInfo(PMGR_LOG_ID3194, "The number of normal disk is %u "
+        DBG_LogInfo(PMGR_LOG_ID3194, "The number of remaining disk can rw except disk(%u) is %u "
                           "while the number of raid member disk is %u DG(%u).",
-                           normalDiskNumInDg, raidMemberDiskNum,taskRcd->dgId);
+                          taskRcd->diskId, diskCanRwNumInDg, raidMemberDiskNum, taskRcd->dgId);
     }
 
     setForceReconFailFlag(taskRcd->taskId, isForceReconFail);
@@ -5682,3 +5682,141 @@
     return;
 }
 
+/**************************************************************************
+    :  ѯdgпɶдԤʧЧ//ععδɣ
+           
+:  poolObj      poolṹָ
+           dgId         ӲDG
+:    
+ֵ  :  normalDiskNum  
+    :  
+**************************************************************************/
+void getDiskCanRwNumInDg(PMGR_OBJ_S *poolObj, diskid_t selfDiskId, dgid_t dgId, 
+                         uint32_t *diskCanRwNumInDg, uint32_t *diskTotalNumInDg)
+{
+    uint32_t index;
+    diskid_t memberDiskId;
+    uint32_t memberDiskNum;
+    uint32_t diskCanRwNum = 0;
+    uint32_t diskTotalNum = 0;
+    PMGR_DISK_INFO_S *diskInfo = NULL;
+    DISK_POOL_MEMBER_DISK_S *poolCfgDiskInfo = NULL;
+
+    poolCfgDiskInfo = &poolObj->memberDiskInfo;
+    memberDiskNum = poolCfgDiskInfo->memberDiskNum;
+    
+    for (index = 0; index < memberDiskNum; index++)
+    {
+        memberDiskId = poolCfgDiskInfo->memberDiskId[index];
+        diskInfo = getLocalDiskInfo(memberDiskId);
+                
+        spin_lock(&diskInfo->diskLock);      
+        if (dgId == diskInfo->dgId) 
+        {
+            diskTotalNum++;
+            
+            if (DISKPOOL_MEMBER_DISK_NORMAL == diskInfo->diskState)
+            {
+                diskCanRwNum++;
+            }
+            else if ((DISKPOOL_MEMBER_DISK_HALFLIFE == diskInfo->diskState ||
+                      DISKPOOL_MEMBER_DISK_SLOWDISK == diskInfo->diskState ||
+                      DISKPOOL_MEMBER_DISK_SLOWRECON == diskInfo->diskState) && 
+                      !diskInfo->isReconFinish && memberDiskId != selfDiskId)
+            {
+                diskCanRwNum++;
+            }
+        }
+        spin_unlock(&diskInfo->diskLock);
+    }
+    
+    *diskCanRwNumInDg = diskCanRwNum;
+    *diskTotalNumInDg = diskTotalNum;
+    
+    return;
+}
+
+/**************************************************************************
+    :  жָӲͲ㼶Ƿ
+:  poolId - ӲID
+           tierId - Ӳ㼶
+:  
+ֵ  :  TRUE/FALSE
+    :  
+**************************************************************************/
+uint32_t isTaskScheduleCanStart(poolid_t poolId, uint8_t tierId)
+{
+    if (poolId < MAX_POOL_NUM && tierId < TIER_TYPE_BUTT)
+    {
+        if (g_taskSchedulePauseTime[poolId][tierId] == 0)
+        {
+            return TRUE;
+        }
+        else
+        {
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
+/**************************************************************************
+    :  Ӳָ㼶ͣ
+:  poolId - ӲID
+           tierId - Ӳ㼶
+           pauseTime - ͣʱ
+:  
+ֵ  :  
+    :  
+**************************************************************************/
+void setTaskSchedulePauseTime(poolid_t poolId, uint32_t tierId, uint32_t pauseTime)
+{    
+    if (poolId < MAX_POOL_NUM && tierId < TIER_TYPE_BUTT)
+    {
+        g_taskSchedulePauseTime[poolId][tierId] = pauseTime;
+    }
+    else
+    {
+        DBG_LogWarning(NO_LOGID, "Set task schedule can start, param is invalid, pool(%u) tier(%d).",
+                       poolId, tierId);
+    }
+    
+    return;
+}
+
+/**************************************************************************
+    :  ǷҪͣȵı⵽ͣ5ӣͣȵı
+:  
+:  
+ֵ  :  
+    :  
+**************************************************************************/
+void checkAndClearTaskSchedulePauseTime(void)
+{
+    uint32_t poolId, tierId;
+
+    for (poolId = 0; poolId < MAX_POOL_NUM; poolId++)
+    {
+        for (tierId = TIER_TYPE_SSD; tierId < TIER_TYPE_BUTT; tierId++)
+        {
+            if (g_taskSchedulePauseTime[poolId][tierId] == 0)
+            {
+                continue;
+            }
+            
+            g_taskSchedulePauseTime[poolId][tierId]++;
+            
+            if (g_taskSchedulePauseTime[poolId][tierId] > MAX_TASK_SCHEDULE_PAUSE_TIME)
+            {
+                g_taskSchedulePauseTime[poolId][tierId] = 0;
+                DBG_LogWarning(NO_LOGID, "Task schedule has paused exceed %d min, pool(%u) tier(%d).",
+                       MAX_TASK_SCHEDULE_PAUSE_TIME, poolId, tierId);
+            }
+        }
+    }
+
+    return;
+}
+
+
--- ./source/private_module/pmgr/pmgr_timeout_ctrl.c	2018-02-09 13:47:03.000000000 +0000
+++ ./source/private_module/pmgr/pmgr_timeout_ctrl.c.hotpatch	2020-04-17 12:52:21.000000000 +0000
@@ -347,7 +347,7 @@
 
     return;
 }
-
+extern void checkAndClearTaskSchedulePauseTime(void);
 /**************************************************************************
     :  ʱ
 :  
@@ -358,7 +358,7 @@
 void pmgrTimeOutTimerHanlde(void* timerArg)
 {
     handleTimeOutTask();
-
+    checkAndClearTaskSchedulePauseTime();
     (void)timerArg;
     return;
 }
