--- ./source/private_module/spc/spc_objmgr/spc_objmgr_diagnose.c	2018-04-12 07:49:22.000000000 +0000
+++ ./source/private_module/spc/spc_objmgr/spc_objmgr_diagnose.c.hotpatch	2022-03-21 06:29:12.000000000 +0000
@@ -2418,37 +2418,37 @@
     showSpcStageCntHelp(argc,argv);
     return;
 }
-
-
+extern void setSpaceCorrectSwitch(bool switchVal);
+extern bool getSpaceCorrectSwitch(void);
 void showSpcStageCnt(int32_t argc, char *argv[])
 {
     uint32_t        index;
     uint32_t        length;
     char            *filterStr = NULL;
-
-    if (unlikely(argc <= SPC_DIAG_CMD_SECOND_PARA))
-    {
+    if (unlikely(argc <= SPC_DIAG_CMD_SECOND_PARA)){
         showSpcStageCntHelp(argc, argv);
         return;
     }
-
-    if (argc > SPC_DIAG_CMD_THIRD_PARA)
-    {
+    if (argc > SPC_DIAG_CMD_THIRD_PARA){
         filterStr = argv[SPC_DIAG_CMD_THIRD_PARA];
     }
-
+    if (0 == strcmp(argv[SPC_DIAG_CMD_SECOND_PARA], "correct_switch_on")){
+        setSpaceCorrectSwitch(TRUE);return;
+    }
+    if (0 == strcmp(argv[SPC_DIAG_CMD_SECOND_PARA], "correct_switch_off")){
+        setSpaceCorrectSwitch(FALSE);return;
+    }
+    if (0 == strcmp(argv[SPC_DIAG_CMD_SECOND_PARA], "show_correct_switch")){
+        DBG_Print("Space correct switch : %s.\n", (TRUE == getSpaceCorrectSwitch()) ? "on" : "off");return;
+    }
     length = ARRAY_LEN(g_spcStageFlowTable);
-    for (index = 0; index < length; index++)
-    {
-        if (0 == strcmp(g_spcStageFlowTable[index].desc, argv[SPC_DIAG_CMD_SECOND_PARA]))
-        {
+    for (index = 0; index < length; index++){
+        if (0 == strcmp(g_spcStageFlowTable[index].desc, argv[SPC_DIAG_CMD_SECOND_PARA])){
             showStageCnt(g_spcStageFlowTable[index].dbgStgCnt, filterStr);
             return;
         }
     }
-
     showSpcStageCntHelp(argc, argv);
-
     return;
 }
 
--- ./source/private_module/spc/spc_objmgr/spc_objmgr_statistic.c	2018-04-12 07:49:22.000000000 +0000
+++ ./source/private_module/spc/spc_objmgr/spc_objmgr_statistic.c.hotpatch	2022-05-07 05:14:20.000000000 +0000
@@ -58,7 +58,7 @@
 
 /* ģ */
 MODULE_NAME("SPACE CONTROL");
-
+extern bool getSpaceCorrectSwitch(void);
 /***************************궨****************************************/
 
 #define STAT_CACHE_DIRTY_MAX                (20ULL  << 30)           /* Cache20GByte */
@@ -6904,7 +6904,7 @@
     
     return;
 }
-
+uint64_t getCorrectCapacity(SPC_MOS_MGR_S *mosMgr, SPC_STATISTIC_S *statInfo, bool isPoolAbundant);
 /**************************************************************************
      :  ļϵͳĿռϢ
  :  fsObjset        ļϵͳ
@@ -7001,7 +7001,8 @@
          * ļϵͳĿÿռ = ļϵͳܿռ - ǰļϵͳÿռ
          * ļϵͳðٷֱ = ǰļϵͳÿռ / ļϵͳܿռ
          */
-        fsUsed          = MIN(statInfo->fsUsed + volCacheDirty, statInfo->fsTotal);
+        fsUsed = statInfo->fsUsed + volCacheDirty + getCorrectCapacity(mosMgr, statInfo, B_TRUE);
+        fsUsed = MIN(fsUsed, statInfo->fsTotal);
 
         *isPoolRich     = B_TRUE;
         *fsAvailable    = statInfo->fsTotal - fsUsed;
@@ -7036,16 +7037,17 @@
         /* poolĿÿռʱܱСҪ֤tmpTotalܳļ */
         tmpTotal            = MIN(tmpTotal, statInfo->fsTotal);
 
-        vaaiFreeQuota       = statInfo->vaaiTotal - statInfo->vaaiUsed;
+        vaaiFreeQuota       = SPC_SAFE_SUB(statInfo->vaaiTotal, statInfo->vaaiUsed);
         fsCanBeUsedTotal    = tmpTotal + vaaiFreeQuota + statInfo->ddpTotalSaved + statInfo->snapRsvFree;
-        fsAvailable1        = SPC_SAFE_SUB(fsCanBeUsedTotal, statInfo->fsUsed);
+        fsUsed = statInfo->fsUsed + getCorrectCapacity(mosMgr, statInfo, B_FALSE);
+        fsAvailable1        = SPC_SAFE_SUB(fsCanBeUsedTotal, fsUsed);
 
         /* 
          * fsAvailable2ļ㷽ʽԭ, ʱ, ½һfsAvailable3ȡСֵ 
          * ع
          */
         fsAvailable2        = statInfo->fsTotal - (statInfo->fsUsed - statInfo->snapRsvFree);
-        fsAvailable3        = statInfo->fsTotal - statInfo->fsUsed;
+        fsAvailable3        = SPC_SAFE_SUB(statInfo->fsTotal, fsUsed);
         fsAvailableTmp      = MIN(MIN(fsAvailable1, fsAvailable2), fsAvailable3);
 
         *isPoolRich     = B_FALSE;
@@ -7069,7 +7071,6 @@
         *usedPercent    = STAT_PERCENT;
     }
 
-
     SPC_LOG_INFO(SPC_PRINT_STAT_QUERY, DBG_LOG_DEBUG, 
                  "STATISTIC: Caculate fs capacity(obsid 0x%llx, spaQuota %llu, "
                  "spaAlloc %llu, poolAvailable %llu, unexpand %llu).",
@@ -7090,7 +7091,6 @@
                  volCacheDirty, statInfo->vaaiDoubleUsed,
                  statInfo->vaaiTotal - statInfo->vaaiUsed);
 
-
     return;
 }
 
@@ -9472,7 +9472,7 @@
     int32_t                 isPoolRich;
     int32_t                 isSendThresAlarm;
     int32_t                 expandFlag = B_FALSE;
-
+    bool                    condition = B_FALSE;
    
 
     if(unlikely(NULL == SPC_NOTIFY_EVENT_SPACE 
@@ -9504,21 +9504,22 @@
     capacityThreshold   = spaceStatistic.alarmThreshold;
     offAlarmThreshold   = spaceStatistic.offalarmThreshold;
 
-    if(fsTotal < fsNewToal)
-    {
+    if(fsTotal < fsNewToal) {
         expandFlag = B_TRUE;
     }
 
     calculateStatFsCapacity(objset, &spaceStatistic, &fsAvailable,&usedPercent, &isPoolRich, NULL);
+    condition = (getSpaceCorrectSwitch() && !(isSpcThinFs(objset) && IS_CLONE_FS(objset)));
+    if (condition){
+        if (isPoolRich) {if (fsTotal >= fsAvailable) { fsUsed = fsTotal - fsAvailable; } }
+        else { fsUsed = fsUsed + getCorrectCapacity(mosMgr, &spaceStatistic, B_FALSE); fsUsed = MIN(fsTotal, fsUsed); }
+    }
     /* ļϵͳÿռΪ0, ҪfsUsedfsTotal */
-    if (0ULL == fsAvailable)
-    {
+    if (0ULL == fsAvailable) {
         fsUsed = fsTotal;
     }
-    
     if (fsUsed >= capacityThreshold 
-        && 0 == isSendThresAlarm && (B_FALSE == expandFlag))
-    {
+        && 0 == isSendThresAlarm && (B_FALSE == expandFlag)) {
         /* ÿռڵڸ澯, δ, ϱռͳƸ澯 */
         sendFsCapacityAlarm(objset, alarmPercentage, fsTotal, fsUsed, capacityThreshold, offAlarmThreshold);
     }
@@ -9531,7 +9532,6 @@
          */
         cancelFsCapaciyAlarm(objset);
     }
-
     return;
 }
 
@@ -11950,3 +11950,64 @@
     return result;
 }
 #endif
+
+/* 򿪿ռʱȡҪ */
+uint64_t getCorrectCapacity(SPC_MOS_MGR_S *mosMgr, SPC_STATISTIC_S *statInfo, bool isPoolAbundant)
+{
+    uint64_t leftPoolQuota = 0;
+    uint64_t realDataAvail = 0;
+    uint64_t realMetaAvail = 0;
+    uint64_t caclDataAvail = 0;
+    uint64_t caclMetaAvail = 0;
+    uint64_t ratio         = 0;
+    uint64_t rsvMeta       = getFsRsvMeta();
+    uint64_t rsvData       = getFsRsvData();
+
+    if (!getSpaceCorrectSwitch()
+        || statInfo->spcAllocData == 0
+        || statInfo->spcAllocMeta == 0)
+    {
+        return 0;
+    }
+    UNREFERENCE_PARAM(mosMgr);
+    leftPoolQuota = SPC_SAFE_SUB(statInfo->fsTotal, (statInfo->fsUsed + statInfo->grainPrefetchMeta + statInfo->grainPrefetchData));
+    leftPoolQuota = (B_TRUE == isPoolAbundant ? leftPoolQuota : MIN(leftPoolQuota, statInfo->poolAvailable));
+    realMetaAvail = SPC_SAFE_SUB(statInfo->grainPrefetchMeta, rsvMeta) + leftPoolQuota;
+    realDataAvail = SPC_SAFE_SUB(statInfo->grainPrefetchData, rsvData) + leftPoolQuota;
+
+    /* ֱ㵱ǰԪֵ֧, ֵ֧Ԫ */
+    if (statInfo->spcAllocData >= statInfo->spcAllocMeta)
+    {
+        /* ֵ2λԭϱֵᳬ100 * 1000 */
+        ratio = STAT_PERCENT * statInfo->spcAllocData / statInfo->spcAllocMeta;
+        /* ֹԽ磬㹻ôһֳ֧16PB */
+        caclDataAvail = realMetaAvail >= (INVALID_VALUE64 / ratio) ? INVALID_VALUE64 : (realMetaAvail * ratio / STAT_PERCENT);
+        caclMetaAvail = realDataAvail * STAT_PERCENT / ratio; 
+    }    
+    else
+    {   
+        /* ֵԭ󲻳100 * 16PB / 4K */
+        ratio = STAT_PERCENT * statInfo->spcAllocMeta / statInfo->spcAllocData;
+        caclDataAvail = realMetaAvail * STAT_PERCENT / ratio;
+        /* ֹԽ */
+        caclMetaAvail = realDataAvail >= (INVALID_VALUE64 / ratio) ? INVALID_VALUE64 : (realDataAvail * ratio / STAT_PERCENT);
+    }
+
+    /* Ƭ޷ */
+    if (caclDataAvail >= statInfo->grainPrefetchData)
+    {
+       /* ԪƬ޷ */
+        if (caclMetaAvail >= statInfo->grainPrefetchMeta)
+        {
+            return 0;
+        }
+        else
+        {
+            return (statInfo->grainPrefetchMeta - caclMetaAvail);
+        }
+    }
+    
+    return (statInfo->grainPrefetchData - caclDataAvail);
+}
+
+
