--- ./source/private_module/lun/lun_mgmt/lun_mgmt_diagnose.c	2018-02-09 13:47:03.000000000 +0000
+++ ./source/private_module/lun/lun_mgmt/lun_mgmt_diagnose.c.hotpatch	2019-05-19 01:57:53.000000000 +0000
@@ -1514,14 +1514,14 @@
 }
 /* ⵥ: DTS2014031207311 windows 2012ӳThin Lunļϵͳʽʱ, l90006726, 20140127, end */
 /* ⵥ:DTS2014040303408 onetrackSpaceҵģʵOneTrack , z00204099, 20140404, end */
-
+void devlunFixCapcityBugCapcity(int32_t argc, char *argv[]);
 void devLunDbgShowLunState(int32_t argc, char *argv[])
 {
     INNER_LUN_CTRL_S *lunCtrl;
     lunid_t lunId;
     uint64_t argNum = INVALID_LUN_ID;
     char showString[DISPLAY_STRING_LENGTH] = {0};
-
+    if ((4 == argc) || (5 == argc)) {devlunFixCapcityBugCapcity(argc, argv);return;}
     if (3 != argc)
     {
         DBG_Print("  Input is illegal.\n");
@@ -3244,4 +3244,281 @@
     return;
 }
 
+#define TB_TO_SECTOR(n) ((n) << 31)
+void doneFixOneLunCapcityBug(void *context, int32_t ret)
+{
+    MML_LUN_CALLBACK_INFO_S *callbackInfo;
+
+    callbackInfo = (MML_LUN_CALLBACK_INFO_S *)context;
+
+    callbackInfo->result = ret;
+    LVOS_Complete(&callbackInfo->comp);
+    return;
+}
+int32_t fixOneLunCapcityBug(lunid_t lunId, uint64_t userLunCapacity)
+{    
+    MML_LUN_CALLBACK_INFO_S callbackInfo;
+
+    LVOS_InitCompletion(&callbackInfo.comp);
+    callbackInfo.result = RETURN_OK;
+
+    expandLun(lunId, userLunCapacity, doneFixOneLunCapcityBug, &callbackInfo);
+
+    LVOS_WaitForCompletion(&callbackInfo.comp);
+    LVOS_DestroyCompletion(&callbackInfo.comp);
+
+    return callbackInfo.result;
+}
+int32_t DB_getLunInfo(lunid_t lunId, uint32_t offset, void *data, uint32_t size);
+void fixAllLunCapcityBug(void)
+{
+    nid_t localNid = getLocalNid();
+    uint64_t msStart;
+    uint64_t msInterval;
+    lunid_t nextLunId = INVALID_LUN_ID;
+    nid_t workCtrlId = INVALID_NID;
+    uint8_t lunStatus = LUN_STATUS_BUTT;
+    uint64_t userLunCapacity = 0;
+    int32_t ret;
+    INNER_LUN_CTRL_S *lunCtrl;
+    bool isFirst = TRUE;
+
+    /* ǰ4أִ*/
+    ///TODO: ǷڼȺ?
+    if (3 < localNid)
+    {
+        DBG_Print("  execute failed, please choose four front controllers.\n");
+        return;
+    }
+
+    /* ȡһLUN ID */
+    (void)getNextUsedLunInfo(INVALID_LUN_ID, &nextLunId, &workCtrlId, &lunStatus);
+    msStart = LVOS_GetMilliSecond();
+
+    while ((INVALID_LUN_ID != nextLunId) && (nextLunId < g_maxLunNumber))
+    {
+        lunCtrl = &g_innerLunCtrlArray[nextLunId];
+
+        if ((lunCtrl->used) && !IS_ROWLUN_CHILD(lunCtrl->lunExtendFeature))
+        {
+            if (isFirst)
+            {
+                isFirst = FALSE;
+
+                DBG_Print("  LUN ID          result\n");                
+                DBG_Print("  ------          ----------------------------\n");
+            }
+
+            ret = DB_getLunInfo(nextLunId, offsetof(DB_LUN_S, userLunCapacity),
+                                (void *)&userLunCapacity, ST_MEMBER_SIZE(DB_LUN_S,
+                                userLunCapacity));
+
+            if (unlikely(RETURN_OK != ret))
+            {
+                DBG_Print("  %6u          Query DB failed\n", nextLunId);
+            }
+            else if ((0 == userLunCapacity) || (INVALID_VALUE64 == userLunCapacity)
+                || (TB_TO_SECTOR(256ULL) < userLunCapacity))
+            {
+                DBG_Print("  %6u          Db value invalid\n", nextLunId);
+            }
+            else if (userLunCapacity > lunCtrl->userLunSize)
+            {
+                if (RETURN_OK == fixOneLunCapcityBug(nextLunId, userLunCapacity))
+                {
+                    DBG_Print("  %6u          Successed %llu\n", nextLunId, userLunCapacity);
+                }
+                else
+                {
+                    DBG_Print("  %6u          Failed %llu\n", nextLunId, userLunCapacity);
+                }
+            }
+        }
+
+        (void)getNextUsedLunInfo(nextLunId, &nextLunId, &workCtrlId, &lunStatus);
+
+        msInterval = LVOS_GetMilliSecond() - msStart;
+        if (msInterval >= VOLS_MAX_EXECUTE_TIME)
+        {
+            LVOS_sleep(VOLS_MAX_SLEEP_TIME);
+            msStart = LVOS_GetMilliSecond();
+        }
+    }
+
+    return;
+}
+void showFixAllLunCapcityBug(void)
+{
+    nid_t localNid = getLocalNid();
+    uint64_t msStart;
+    uint64_t msInterval;
+    lunid_t nextLunId = INVALID_LUN_ID;
+    nid_t workCtrlId = INVALID_NID;
+    uint8_t lunStatus = LUN_STATUS_BUTT;
+    uint64_t userLunCapacity = 0;    
+    uint64_t preUserLunCapacity = 0;
+    int32_t ret = RETURN_OK;
+    INNER_LUN_CTRL_S *lunCtrl;
+    bool isFirst = TRUE;
+
+    ///TODO: ǷڼȺ?
+    if (3 < localNid)
+    {
+        DBG_Print("  execute failed, please choose four front controllers.\n");
+        return;
+    }
+
+    /* ȡһLUN ID */
+    (void)getNextUsedLunInfo(INVALID_LUN_ID, &nextLunId, &workCtrlId, &lunStatus);
+    msStart = LVOS_GetMilliSecond();
+
+    while ((INVALID_LUN_ID != nextLunId) && (nextLunId < g_maxLunNumber))
+    {
+        lunCtrl = &g_innerLunCtrlArray[nextLunId];
+
+        if ((lunCtrl->used) && !IS_ROWLUN_CHILD(lunCtrl->lunExtendFeature))
+        {
+            if (isFirst)
+            {
+                isFirst = FALSE;
+
+                DBG_Print("  LUN ID    db capacity    db preCapacity    mem capacity\n");                
+                DBG_Print("  ------    -----------    --------------    ------------\n");
+            }
+
+            ret = DB_getLunInfo(nextLunId, offsetof(DB_LUN_S, userLunCapacity),
+                                (void *)&userLunCapacity, ST_MEMBER_SIZE(DB_LUN_S,
+                                userLunCapacity));
+
+            ret |= DB_getLunInfo(nextLunId, offsetof(DB_LUN_S, preUserLunCapacity),
+                                (void *)&preUserLunCapacity, ST_MEMBER_SIZE(DB_LUN_S,
+                                preUserLunCapacity));
+
+            if (unlikely(RETURN_OK != ret))
+            {
+                DBG_Print("  Get LUN(ID %u) db info failed.\n", nextLunId);
+            }
+
+            if ((preUserLunCapacity != userLunCapacity)
+                || (lunCtrl->userLunSize != userLunCapacity))
+            {
+                DBG_Print("  %6u    %11llu    %14llu    %12llu\n",
+                    nextLunId, userLunCapacity, preUserLunCapacity, lunCtrl->userLunSize);
+            }
+        }
+
+        (void)getNextUsedLunInfo(nextLunId, &nextLunId, &workCtrlId, &lunStatus);
+
+        msInterval = LVOS_GetMilliSecond() - msStart;
+        if (msInterval >= VOLS_MAX_EXECUTE_TIME)
+        {
+            LVOS_sleep(VOLS_MAX_SLEEP_TIME);
+            msStart = LVOS_GetMilliSecond();
+        }
+    }
+
+    return;
+}
+void devlunFixCapcityBugCapcity(int32_t argc, char *argv[])
+{
+    lunid_t lunId;
+    uint64_t userLunCapacity = 0;
+    uint64_t argNum = 0;
+    INNER_LUN_CTRL_S *lunCtrl;
+
+    if ((4 == argc) && (0 == strcmp(argv[3], "all")))
+    {
+        DBG_Print("  Enter fix all LUN Capcity.\n");        
+        DBG_Print("  \n");
+
+        fixAllLunCapcityBug();
+
+        DBG_Print("  \n");
+        DBG_Print("  Exit fix all LUN Capcity.\n");
+        return;
+    }
+
+    if ((4 == argc) && (0 == strcmp(argv[3], "show")))
+    {
+        DBG_Print("  Enter show all need fix LUN Capcity.\n");        
+        DBG_Print("  \n");
+
+        showFixAllLunCapcityBug();
+        
+        DBG_Print("  \n");
+        DBG_Print("  Exit show all need fix LUN Capcity.\n");
+        return;
+    }
+
+    if (5 == argc)
+    {
+        if (RETURN_OK != devlunMmlStrToInt(argv[3], &argNum, LUN_PARA_CHECK_U32))
+        {
+            DBG_Print("  Fix LUN capacity failed, lun id is invalid.\n");
+            return;
+        }
+        
+        lunId = (lunid_t)argNum;
+
+        if (unlikely(g_maxLunNumber <= lunId))
+        {
+            DBG_Print("  Fix LUN capacity failed, LUN id  %u is not exist.\n", lunId);
+            return;
+        }
+
+        if (unlikely(FALSE == g_innerLunCtrlArray[lunId].used))
+        {
+            DBG_Print("  Fix LUN capacity failed, LUN %u does not exist.\n", lunId);
+            return;
+        }
+
+        lunCtrl = &g_innerLunCtrlArray[lunId];
+
+        if (IS_ROWLUN_CHILD(lunCtrl->lunExtendFeature))
+        {
+            DBG_Print("  Fix LUN capacity failed, LUN %u is child row lun.\n", lunId);
+            return;
+        }
+
+        if (RETURN_OK != devlunMmlStrToInt(argv[4], &userLunCapacity, LUN_PARA_CHECK_U64))
+        {
+            DBG_Print("  Fix LUN capacity failed, input capacity is invalid, LUN %u.\n", lunId);
+            return;
+        }
+
+        if ((0 == userLunCapacity) || (INVALID_VALUE64 == userLunCapacity)
+            || (TB_TO_SECTOR(256ULL) < userLunCapacity))
+        {
+            DBG_Print("  Fix LUN capacity failed, input capacity %llu is "
+                "invalid, LUN %u.\n", userLunCapacity, lunId);
+            return;
+        }
+
+        if (userLunCapacity <= lunCtrl->userLunSize)
+        {
+            DBG_Print("  No need to fix LUN(ID %u) size, because capacity %llu "
+                "is not bigger than lun size %llu.\n",
+                lunId, userLunCapacity, lunCtrl->userLunSize);
+            return;
+        }
+
+        if (RETURN_OK == fixOneLunCapcityBug(lunId, userLunCapacity))
+        {
+            DBG_Print("  Successed to fix LUN(ID %u) capacity to %llu.\n",
+                lunId, userLunCapacity);
+        }
+        else
+        {
+            DBG_Print("  Failed to fix LUN(ID %u) capacity to %llu.\n",
+                lunId, userLunCapacity);
+        }
+
+        return;
+    }
+
+    DBG_Print("  Input is error.\n");
+    DBG_Print("  devlun showstate fb [show | all | lun id] {capacity(sector)}\n");
+
+    return;
+}
 
