--- ./source/private_module/bdm/features/extra_dif/sio_extra_dif.c	2018-02-09 07:36:26.000000000 +0000
+++ ./source/private_module/bdm/features/extra_dif/sio_extra_dif.c.hotpatch	2021-02-07 03:23:54.000000000 +0000
@@ -33,16 +33,16 @@
 /*Ϊ0ֽڱʾDIFеİ汾źAAP*/
 /*ע:ΪС˵ԭ򣬴˴Ƿ*/
 #define SIO_EXTRA_DIF_VER_APP_BIT       (0xFFFFFFFF0000FFFF)
-
-
+// ڽв̵ȫ
+bool g_sioExtraDifWholeSampling = FALSE;
 /*ȫֱ*/
 bool g_sioExtraDifSwitchFlag = TRUE;               /*DIFܿ,ĬΪ*/
 uint16_t g_sioExtraDifCycleInterval = 30;           /*DIF,λΪ*/
 uint16_t g_sioExtraDifCycleCount = 0;               /* ¼ʱʹSIOͳƵ1sʱ*/
 atomic_t g_sioExtraDifStatBusy = ATOMIC_INIT(0);    /*DIF㵱ǰIO*/
 bool g_sioExtraDifCmpSwitchFlag = TRUE;             /*дIO DIFȽϹܿ,ĬΪ*/
-
-
+uint16_t g_sioExtraDifCycleIntervalPatch = 0;
+extern spinlock_t g_sdSdlock;
 SIO_DEBUG_EXTRA_DIF_SWITCH_S g_sioExtraDifDebug = {0};
 
 void sioExtraDifNewReadReq(REQ_S *req);
@@ -60,21 +60,21 @@
 **************************************************************************/
 void sioExtraDifSetSwitchAndCycle(bool flag, uint16_t newCycle)
 {   
-    /*ֵͬҪ޸*/
     if(flag == g_sioExtraDifSwitchFlag  && newCycle == g_sioExtraDifCycleInterval)
     {
         return;
     }
-
-    /*ҪӡƵ*/
     DBG_LogInfo(LOG_ID_SIO_0191, "ExtraDif: change, switch(%u to %u), cycle(%u to %u).",
-                g_sioExtraDifSwitchFlag, 
-                flag,
-                g_sioExtraDifCycleInterval,
-                newCycle);
-    
+                g_sioExtraDifSwitchFlag, flag,
+                g_sioExtraDifCycleInterval, newCycle);
+    spin_lock(&g_sdSdlock);
     g_sioExtraDifSwitchFlag = flag;
-    g_sioExtraDifCycleInterval = newCycle;
+    if (g_sioExtraDifWholeSampling == TRUE) {
+        g_sioExtraDifCycleIntervalPatch = newCycle;
+    } else {
+        g_sioExtraDifCycleInterval = newCycle;
+    }  
+    spin_unlock(&g_sdSdlock);
     return;
 }
 
@@ -243,7 +243,7 @@
     /*DIFλͬ򷵻ERROR*/
     return RETURN_ERROR;
 }
-
+extern void sioExtraDifErrRecord(REQ_S *req);
 /**************************************************************************
        : sioExtraDifNotifyDrv
              : ֪ͨDIF
@@ -263,7 +263,7 @@
      
     /*֪ͨSASDIF*/
     sioDifErrNotifyDrv((uint32_t)req->objectId, sio->linkInfo, DRV_WRITE_SAMPLE_CMD_DIF_ERROR_SINGLEPATH);
-    
+    sioExtraDifErrRecord(req);
     return;
 }
 
@@ -742,7 +742,7 @@
     return;
 }
 
-
+extern void sioExtraDifErrReportHalfLife(void);
 /**************************************************************************
        : sioExtraDifCycleCheck
              : ⸽DIFǣڱ״̬
@@ -753,7 +753,7 @@
 **************************************************************************/
 bool sioExtraDifCycleCheck()
 {
-    /*Ϊ0ʱIO*/
+    sioExtraDifErrReportHalfLife();
     if( 0 == g_sioExtraDifCycleInterval)
     {
         g_sioExtraDifCycleCount = 0;
@@ -1100,3 +1100,234 @@
     /*End Modified by t00352166  DTS2017022803150  201700303*/
     return;
 }
+
+
+
+// ȫʱ3ӣλ:jiffies
+#define SIO_EXTRA_DIF_FULL_SAMPLE_TIME  (3*60*HZ)
+ 
+// ϱʧЧǰʱֵ1죬λ:jiffies
+#define SIO_TIME_THRESHOLD_ONE_DAY      (1*24*3600*HZ)
+ 
+// ϱʧЧǰʱֵ3£λ:
+#define SIO_TIME_THRESHOLD_THREE_MONTH  (3*30*24*3600)
+ 
+// ϱʧЧdifֵͬһۼ3dif󣬸ݴ߼жϵĺ궨ֵΪ2
+#define SIO_DIF_ERROR_HALFLIFE_THRESHOLD (2)
+ 
+// ־ӡ1Сʱ
+#define SIO_PATCH_PRINT_LIMIT_LOG_INTERVAL   (1*60*60*HZ)
+ 
+// ־ӡ1Сʱ8
+#define SIO_PATCH_PRINT_LIMIT_LOG_NUM        (8)
+ 
+// ϴϱʧЧӲк
+char g_lastReportDiskSn[DISK_SN_LEN] = {0};
+ 
+// ϴϱʧЧʱ
+uint64_t g_lastReportHalflifeTime = 0;
+
+// ̵ȫܿ
+bool g_sioExtraDifFuncSwitch = TRUE;
+
+// ӳһ30s
+#define SIO_PATCH_REPORT_DELAY_TIME   (30*HZ)
+
+/* ӲdifͳϢṹ */
+typedef struct tagSIO_EXTRA_DIF_ENHANCE_PARA_S
+{
+    char sn[DISK_SN_LEN];       /* Ӳк */
+    uint32_t difErrCnt;         /* DIF */
+    uint64_t firstDifErrTime;   /* һdifʱ */
+    uint64_t meetReportConTime; /* ϱʱ */
+} SIO_EXTRA_DIF_ENHANCE_PARA_S;
+ 
+/* ӲdifͳϢȫֱ */
+SIO_EXTRA_DIF_ENHANCE_PARA_S g_ExtraDifEnhancePara = {0};
+ 
+/**************************************************************************
+   : SioClearDifEnhancePara
+     : ȫֱݣָΪʼ״ֵ̬
+ : 
+ : 
+   ֵ: 
+     : 
+**************************************************************************/
+void SioClearDifEnhancePara(void)
+{   
+    memset(g_ExtraDifEnhancePara.sn, 0, DISK_SN_LEN);
+    g_ExtraDifEnhancePara.difErrCnt = 0;
+    g_ExtraDifEnhancePara.firstDifErrTime = 0;
+    g_ExtraDifEnhancePara.meetReportConTime = 0;
+  
+    return;
+}
+
+extern void SdDifErrReportHalflifeByDiskSn(uint8_t *sn);
+/**************************************************************************
+   : SioReportSlowDiskHandle
+     : ϱʧЧش
+ : 
+ : 
+   ֵ: 
+     : 
+**************************************************************************/
+void SioReportHalflifeHandle(void)
+{
+    g_sioExtraDifCycleInterval = g_sioExtraDifCycleIntervalPatch;
+    g_sioExtraDifWholeSampling = FALSE;
+    DBG_LogInfo(DBG_LOGID_BUTT, "DIF_PATCH_SPH030: report halflife and restore sample cycle to original value, disk sn(%s), ExtraDifCycle(%u).", 
+        g_ExtraDifEnhancePara.sn, g_sioExtraDifCycleInterval);
+    
+    memcpy(g_lastReportDiskSn, g_ExtraDifEnhancePara.sn, DISK_SN_LEN);
+    g_lastReportHalflifeTime = jiffies;
+      
+    SdDifErrReportHalflifeByDiskSn((uint8_t *)g_ExtraDifEnhancePara.sn);
+    SioClearDifEnhancePara();
+ 
+    return;
+}
+
+/**************************************************************************
+       : sioExtraDifErrRecord
+             : ͳDIFϢ
+ : REQ_S* req    :ǰIO
+ : 
+   ֵ    : 
+             :
+**************************************************************************/
+void sioExtraDifErrRecord(REQ_S *req)
+{
+    SCSI_DISK_DEVICE_S *disk = NULL;
+    SD_SCSI_DEVICE_S *dev = NULL;
+
+    spin_lock(&g_sdSdlock);
+    if (g_sioExtraDifFuncSwitch != TRUE) {
+        spin_unlock(&g_sdSdlock);
+        return;
+    }
+    spin_unlock(&g_sdSdlock);
+
+    dev = SD_DEVICE_LOOK_UP((uint32_t)req->objectId);
+    if (NULL == dev)
+    {
+    	DBG_LogError(DBG_LOGID_BUTT, "DIF_PATCH_SPH030: dev is NULL, sdevId(%lu).", req->objectId);
+    	return;
+    } 
+    disk = SD_GENERIC_TO_DISK(dev);
+
+    spin_lock(&g_sdSdlock);
+    if (memcmp(g_ExtraDifEnhancePara.sn, disk->sn, DISK_SN_LEN) != 0) {
+        if (g_ExtraDifEnhancePara.difErrCnt == 0) {
+        	BDM_PRINT_LIMIT_PERIOD(SIO_PATCH_PRINT_LIMIT_LOG_INTERVAL, SIO_PATCH_PRINT_LIMIT_LOG_NUM,
+        		DBG_LOG_INFO, DBG_LOGID_BUTT, "DIF_PATCH_SPH030: handle the first dif error, disk sn(%s).", disk->sn);
+        } else {
+        	BDM_PRINT_LIMIT_PERIOD(SIO_PATCH_PRINT_LIMIT_LOG_INTERVAL, SIO_PATCH_PRINT_LIMIT_LOG_NUM,
+        		DBG_LOG_INFO, DBG_LOGID_BUTT, "DIF_PATCH_SPH030: one new disk sn(%s) occur difErr, clear the old ExtraDifEnhancePara info, old disk sn(%s).", 
+        		disk->sn, g_ExtraDifEnhancePara.sn);
+        }
+        // ֹAһdifg_sioExtraDifCycleInterval޸Ϊ0Bֲһdifg_sioExtraDifCycleIntervalPatch󱣴Ϊ0
+        if (g_ExtraDifEnhancePara.firstDifErrTime == 0) {
+        	g_sioExtraDifCycleIntervalPatch = g_sioExtraDifCycleInterval;
+        }
+        // ȫ
+        g_sioExtraDifCycleInterval = 0;
+        g_sioExtraDifWholeSampling = TRUE;
+
+        // ϵͳϢ
+        SioClearDifEnhancePara();
+        // ʼµͳƣdif1¼Ӳsn״δʱ
+        g_ExtraDifEnhancePara.difErrCnt += 1;
+        memcpy(g_ExtraDifEnhancePara.sn, disk->sn, DISK_SN_LEN);
+        g_ExtraDifEnhancePara.firstDifErrTime = jiffies;
+    } else {
+        if (g_ExtraDifEnhancePara.difErrCnt >= SIO_DIF_ERROR_HALFLIFE_THRESHOLD && g_ExtraDifEnhancePara.meetReportConTime == 0) {
+        	g_ExtraDifEnhancePara.meetReportConTime = jiffies;
+        	DBG_LogInfo(DBG_LOGID_BUTT, "DIF_PATCH_SPH030: one disk difErr count is equal or greater than 3, disk sn(%s).", g_ExtraDifEnhancePara.sn);
+        } else if (g_ExtraDifEnhancePara.difErrCnt < SIO_DIF_ERROR_HALFLIFE_THRESHOLD) {
+        	g_ExtraDifEnhancePara.difErrCnt += 1;
+        	DBG_LogInfo(DBG_LOGID_BUTT, "DIF_PATCH_SPH030: one disk difErr count add 1, disk sn(%s).", g_ExtraDifEnhancePara.sn);
+        }
+    }
+    spin_unlock(&g_sdSdlock);
+
+    SD_PUT_DEVICE(dev);	
+}
+
+/**************************************************************************
+   : sioExtraDifErrReportSlowDisk
+     : DIFдϱʧЧ
+ : 
+ : 
+   ֵ: 
+     : 
+**************************************************************************/
+void sioExtraDifErrReportHalfLife(void)
+{
+    spin_lock(&g_sdSdlock); 
+    if (g_sioExtraDifFuncSwitch != TRUE) {
+        spin_unlock(&g_sdSdlock);
+        return;
+    }
+    // ʱȫʱﵽ3ӣԶָΪԭʼֵ
+    if ((g_ExtraDifEnhancePara.firstDifErrTime != 0) && (jiffies - g_ExtraDifEnhancePara.firstDifErrTime >= SIO_EXTRA_DIF_FULL_SAMPLE_TIME)) {
+        g_sioExtraDifCycleInterval = g_sioExtraDifCycleIntervalPatch;
+        g_sioExtraDifWholeSampling = FALSE;
+        g_ExtraDifEnhancePara.firstDifErrTime = 0;
+        DBG_LogInfo(DBG_LOGID_BUTT, "DIF_PATCH_SPH030: restore sample cycle to original value, disk sn(%s), ExtraDifCycle(%u).", g_ExtraDifEnhancePara.sn, g_sioExtraDifCycleInterval);
+    }
+    	
+    // ǷҪϱʧЧӳʱ䳬һڣ飬Ҫ
+    if ((g_ExtraDifEnhancePara.meetReportConTime != 0) && (jiffies - g_ExtraDifEnhancePara.meetReportConTime > SIO_PATCH_REPORT_DELAY_TIME)) {
+        // δϱʧЧοϱ
+        if (g_lastReportHalflifeTime == 0) {          
+            DBG_LogInfo(DBG_LOGID_BUTT, "DIF_PATCH_SPH030: meet report condition, has not reported, disk sn(%s).", g_ExtraDifEnhancePara.sn);
+            SioReportHalflifeHandle();
+        // ѾϱʧЧ
+        } else {
+            // ϴϱδ3
+            if (SIO_JIFFIES_TO_SEC(jiffies - g_lastReportHalflifeTime) <= SIO_TIME_THRESHOLD_THREE_MONTH) {
+                // ϴϱʧЧsn뱾δϱsnͬжʱǷ1죬1챾οϱ
+                if ((memcmp(g_ExtraDifEnhancePara.sn, g_lastReportDiskSn, DISK_SN_LEN) == 0) && (jiffies - g_lastReportHalflifeTime > SIO_TIME_THRESHOLD_ONE_DAY)) {
+                    DBG_LogInfo(DBG_LOGID_BUTT, "DIF_PATCH_SPH030: meet report condition, same disk, in 3 months, over 1 day, disk sn(%s).", 
+                        g_ExtraDifEnhancePara.sn);
+                    SioReportHalflifeHandle();
+                } else {
+                    // difʱδ3»1ʱֵʱͳϢֹ3º1ûdifʱϱһԤʧЧ
+                    BDM_PRINT_LIMIT_PERIOD(SIO_PATCH_PRINT_LIMIT_LOG_INTERVAL, SIO_PATCH_PRINT_LIMIT_LOG_NUM,
+        		        DBG_LOG_INFO, DBG_LOGID_BUTT, "DIF_PATCH_SPH030: meet 3 difErr, but not over 3 months or 1 day, clear difErr info, disk sn(%s).", 
+        		        g_ExtraDifEnhancePara.sn);
+                    SioClearDifEnhancePara();
+                    g_sioExtraDifCycleInterval = g_sioExtraDifCycleIntervalPatch;
+                    g_sioExtraDifWholeSampling = FALSE;                  
+                }
+            // ϴϱѾ3£ܺϴǲͬһ̣ϱ
+            } else {
+                DBG_LogInfo(DBG_LOGID_BUTT, "DIF_PATCH_SPH030: meet report condition, over 3 months, disk sn(%s).", g_ExtraDifEnhancePara.sn);
+                SioReportHalflifeHandle();
+            }
+        }
+    }  
+    spin_unlock(&g_sdSdlock);
+}
+
+bool sioPreHandleRollBackHotpatch(int32_t argc, char *argv[])
+{
+    if (!(argc == 3 && strcmp(argv[2], "BUGLIST202005130022") == 0)){
+        return FALSE;
+    }
+
+    spin_lock(&g_sdSdlock);
+    g_sioExtraDifFuncSwitch = FALSE;
+    if (g_sioExtraDifWholeSampling == TRUE) {
+        g_sioExtraDifCycleInterval = g_sioExtraDifCycleIntervalPatch;
+    }
+    spin_unlock(&g_sdSdlock);
+    DBG_LogInfo(DBG_LOGID_BUTT, 
+        "DIF_PATCH_SPH030: funcSwitch %d, wholeSampling %d, difCycleInterval %u, difCycleIntervalPatch %u.", 
+       g_sioExtraDifFuncSwitch, g_sioExtraDifWholeSampling, g_sioExtraDifCycleInterval, g_sioExtraDifCycleIntervalPatch);
+
+    return TRUE;
+}
+EXPORT_SYMBOL(sioPreHandleRollBackHotpatch);
+
--- ./source/private_module/bdm/sdm/sd/adapter/sd_adapter_device.c	2018-02-09 07:36:26.000000000 +0000
+++ ./source/private_module/bdm/sdm/sd/adapter/sd_adapter_device.c.hotpatch	2021-02-07 03:23:54.000000000 +0000
@@ -3613,3 +3613,24 @@
 /*Begin Modified by l0245290 SR_0000157392_07 20170711*/
 
 
+void SdDifErrReportHalflifeByDiskSn(uint8_t *sn)
+{
+    SD_ADAPTER_DEVICE *adpDev = NULL;
+    
+    adpDev = sdGetAdapterDeviceBySn(sn);
+    if (adpDev == NULL) {
+        return;
+    }
+
+    /* Ӳ̵ */
+    sdSetDiskLedState(adpDev, BDM_DISK_LIGHT_TYPE_ALARM, BDM_DISK_LIGHT_STATE_OPEN);
+    /* Ӳ̱ʧЧ¼ */
+    sdReportDeviceCommonEvent(adpDev->sdevId,
+                              SCSI_DISK_EVENT_HALFLIFE, 
+                              ALL_CTRL_EVENT,
+                              DISK_IMPENDING_FAILURE_DIF_STAT);
+                              
+    DBG_LogInfo(DBG_LOGID_BUTT, "DIF_PATCH_SPH030: report one disk halflife, sdevId(%u), sn(%s).", adpDev->sdevId, sn); 
+}
+EXPORT_SYMBOL(SdDifErrReportHalflifeByDiskSn);
+
--- ./source/private_module/bdm/sdm/sd/stub_v3/stub_sd_debug.c	2018-04-02 08:32:38.000000000 +0000
+++ ./source/private_module/bdm/sdm/sd/stub_v3/stub_sd_debug.c.hotpatch	2021-02-07 03:23:54.000000000 +0000
@@ -188,7 +188,7 @@
 
     DBG_Print("%4u         %-3u        %s\n", sdid, useRate, sdGetDiskTypeString(type));
 }
-
+extern bool sioPreHandleRollBackHotpatch(int32_t argc, char *argv[]);
 void stub_sdDoDebugInquiryDiskUseRate(int32_t argc, char *argv[])
 {
     SD_SCSI_DEVICE_S *dev = NULL;
@@ -198,9 +198,9 @@
     uint32_t cycle = 0;
     uint32_t idx = 0;
 
-    /*Begin Modified by l00245290 DTS2015062304179 20150624*/
-    //DBG_ASSERT(NULL != argv);
-    /*End Modified by l00245290 DTS2015062304179 20150624*/
+    if (sioPreHandleRollBackHotpatch(argc, argv)) {
+        return;
+    }
     
     if ((argc < 3) || (argc > 4))
     {
