--- ./source/private_module/ramcache/cacheobject/cache_obj.c	2018-04-26 09:14:15.000000000 +0000
+++ ./source/private_module/ramcache/cacheobject/cache_obj.c.hotpatch	2021-01-12 09:04:08.000000000 +0000
@@ -55,14 +55,14 @@
 static bool g_allowCreateCacheObjFlag = TRUE;
 spinlock_t   g_createDefaultObjLock;
 #define IS_ALLOW_CREATE_CACHE_OBJ (g_allowCreateCacheObjFlag)
-
-
-
+bool g_getNextCacheObjNoCondition = FALSE;
+bool isAllowCreateCacheObj(void)
+{return g_allowCreateCacheObjFlag;}
 spinlock_t         g_cacheObjGlobalLock;
 static SPIN_LOCK_LIST_HEAD_S g_cacheObjGlobalList[MAX_OBJ_HASH_NUM];
-
+SPIN_LOCK_LIST_HEAD_S *getGlobalListByHashId(uint32_t hashId)
+{return &g_cacheObjGlobalList[hashId];}
 DISK_POOL_CACHE_OBJ_S g_diskPoolCacheObj[MAX_POOL_NUM_IN_CACHE];
-
 REQ_OPS_S g_retryPossReqOps = 
 {
     "retryPossReq",
--- ./source/private_module/ramcache/debug/diagnose/diagnose_cache_chunk.c	2018-02-09 13:47:03.000000000 +0000
+++ ./source/private_module/ramcache/debug/diagnose/diagnose_cache_chunk.c.hotpatch	2021-01-12 09:04:08.000000000 +0000
@@ -3324,27 +3324,27 @@
 
     return RETURN_OK;
 }
-
+void getInvalidCacheobj(void);
+void clearRemainCacheobj(char *argv[]);
+void clearOneCacheobj(char *argv[]);
 /**************************************************************************
      :  ʾstripecacheеckg
  :  argc       : argvԪظ
             argv       : 
- :  
- ֵ  :  
-     :  
 **************************************************************************/
 int32_t diagShowCacheckgInfo(int32_t argc, char *argv[])
 {
     uint64_t poolid = 0;
     uint64_t ckgObjid = 0;
     int32_t ret = RETURN_OK;
-
+    if (argc == 0){getInvalidCacheobj();return ret;}
+    else if (argc == 1){clearRemainCacheobj(argv);return ret;}
+    else if (argc == 2){clearOneCacheobj(argv);return ret;}
     /* 3-4 */
     if (RETURN_OK != checkDiagnoseParamNum(argc, 3, 4, "cache show ckg"))
     {
         return RETURN_ERROR;
     }
-
     /* poolid */
     ret = cacheGetParamU64(argv[1], &poolid);
     if ((RETURN_OK != ret) || (poolid >= MAX_POOL_NUM_IN_CACHE))
--- ./source/private_module/ramcache/debug/diagnose/diagnose_cache_obj.c	2018-02-09 13:47:03.000000000 +0000
+++ ./source/private_module/ramcache/debug/diagnose/diagnose_cache_obj.c.hotpatch	2021-03-16 14:32:51.000000000 +0000
@@ -5749,3 +5749,245 @@
 
     return RETURN_OK;
 }
+
+#include "cache_volume_intf.h"
+ 
+void clearObjCallBack(IN void * arg, IN int32_t result)
+{
+    UNREFERENCE_PARAM(arg);
+    UNREFERENCE_PARAM(result);
+    return;
+}
+
+extern bool g_getNextCacheObjNoCondition;
+#define NO_CONDITITION g_getNextCacheObjNoCondition
+#define MAX_OBJ_HASH_NUM 127
+
+bool isAllowCreateCacheObj(void);
+
+extern SPIN_LOCK_LIST_HEAD_S *getGlobalListByHashId(uint32_t hashId);
+
+#define PUSH_PRINT_BUF_TO_SCREEN(printBufCnt) do{if(*(printBufCnt) > 100){ DBG_Print(""); *(printBufCnt) = 0; }}while(0);
+
+#define GET_NEXT_CACHE_OBJ_START(cacheObj) \
+do{ \
+    uint32_t hashId = 0; \
+    uint32_t iterNum = 0; \
+    uint32_t objSum = 0; \
+    uint32_t cycleCount = 0; \
+    for(hashId = 0; hashId < MAX_OBJ_HASH_NUM; hashId++) \
+    { \
+        SPIN_LOCK_LIST_HEAD_S *objList = NULL; \
+        struct list_head * curNode = NULL; \
+        iterNum = 0; \
+        objList = getGlobalListByHashId(hashId); \
+        objSum = spinLockListCount(objList); \
+        while(iterNum < objSum) \
+        { \
+            iterNum++; \
+            cacheObj = NULL; \
+            lockCacheObjGlobalList(); \
+            if(isAllowCreateCacheObj()) \
+            { \
+                curNode = spinLockListCutFirstNodeNoLock(objList); \
+                if(NULL != curNode) \
+                { \
+                    spinLockListAddTailNoLock(curNode, objList); \
+                    cacheObj = list_entry(curNode, CACHE_OBJ_S, objNode);
+
+#define GET_NEXT_CACHE_OBJ_FOR_DIAG_END(conditition, printBufCnt) \
+                } \
+            } \
+            unlockCacheObjGlobalList(); \
+            PUSH_PRINT_BUF_TO_SCREEN(&printBufCnt); \
+            if(conditition){ break; } \
+            SWITCH_THREADS_BY_NUM(cycleCount, 100); \
+        } \
+        if(conditition){ break; } \
+    } \
+}while(0);
+
+
+void *getPoolCkgTablePatch2(IN poolid_t poolId)
+{
+    CACHE_POOL_CKG_TABLE_S *poolTable = g_cacheCkgTable.poolCkgTable;
+    return poolTable + poolId;
+}
+
+bool isStpBaseErr2(CACHE_OBJ_S* cacheObj)
+{
+    CACHE_BASE_S* cacheBase = cacheObj->stripeCache;
+    if (NULL == cacheBase)
+    {
+        return FALSE;
+    }
+
+    if (GET_BASE_WRITE_PT(cacheBase) == getPoolCkgTablePatch2(GET_BASE_POOL_ID(cacheBase)))
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+#define MAX_CACHE_OBJ_NUM (128)
+typedef struct tagCACHE_REMAIN_OBJ_S
+{
+    volumeid_t volumeId[MAX_CACHE_OBJ_NUM];
+    uint32_t volumeCnt;
+}CACHE_REMAIN_OBJ_S;
+
+CACHE_REMAIN_OBJ_S g_cacheRemainObj;
+
+void initRemainRecord(void)
+{
+    memset(&g_cacheRemainObj, 0, sizeof(CACHE_REMAIN_OBJ_S));
+}
+
+void recordRemainObj(CACHE_OBJ_S *cacheObj)
+{
+
+    CACHE_REMAIN_OBJ_S *cacheRemainObj = &g_cacheRemainObj;
+    if(cacheRemainObj->volumeCnt >= MAX_CACHE_OBJ_NUM)
+    {
+       return; //??2:??128 ?????,?????????????????
+    }
+
+    cacheRemainObj->volumeId[cacheRemainObj->volumeCnt] = cacheObj->volumeId;
+    cacheRemainObj->volumeCnt++;
+}
+
+bool isObjRemain(CACHE_OBJ_S *cacheObj)
+{
+    CACHE_REMAIN_OBJ_S *cacheRemainObj = &g_cacheRemainObj;
+    uint32_t i;
+    bool res = FALSE;
+
+    for (i = 0; i < cacheRemainObj->volumeCnt; i++)
+    {
+        if (cacheRemainObj->volumeId[i] == cacheObj->volumeId)
+        {
+            res = TRUE;
+            break;
+        }
+    }
+
+    return res;
+}
+
+void getInvalidCacheobj(void)
+{    
+    CACHE_OBJ_S *cacheObj = NULL;
+    CACHE_OBJ_S *volumeObj = NULL;
+    uint32_t printBufCnt = 0;
+    uint32_t remainCnt = 0;
+    uint32_t newPoolCnt = 0;
+    uint32_t samePoolCnt = 0;
+    uint32_t normalCnt = 0;
+    initRemainRecord();
+    
+    GET_NEXT_CACHE_OBJ_START(cacheObj);
+
+        volumeObj = getVolumeCacheObjIntf(cacheObj->volumeId);
+        if (NULL == volumeObj)
+        {
+            DBG_LogInfo(0, "Ramain pool:%u, vol:0x%llx", cacheObj->poolId, cacheObj->volumeId);
+            remainCnt++;
+            if(remainCnt <= 10) //??3:????10??????diagnose?
+            {
+                DBG_PrintBuf("cur remain obj volId:0x%llx, poolId:%u, index:%u\n", cacheObj->volumeId, cacheObj->poolId, remainCnt);
+            }
+            recordRemainObj(cacheObj);
+        }
+        else if (isStpBaseErr2(cacheObj))
+        {
+            DBG_LogInfo(0, "New pool:%u, vol:0x%llx", cacheObj->poolId, cacheObj->volumeId);
+            newPoolCnt++;
+        }
+        else if (cacheObj->volumeCache != NULL && cacheObj->volumeCache->state == CACHE_BASE_DELETING)
+        {
+            DBG_LogInfo(0, "Same pool:%u, vol:0x%llx", cacheObj->poolId, cacheObj->volumeId);
+            samePoolCnt++;
+        }
+        else
+        {
+            normalCnt++;
+        }
+
+        printBufCnt += 2;
+    GET_NEXT_CACHE_OBJ_FOR_DIAG_END(NO_CONDITITION, printBufCnt)
+
+    DBG_PrintBuf("remain:%u, newPool:%u, samePool:%u, normal:%u\n",
+                 remainCnt, newPoolCnt, samePoolCnt, normalCnt);
+    DBG_LogInfo(0, "remainCnt:%u, newPoolCnt:%u, samePoolCnt:%u, normalCnt:%u.", remainCnt, newPoolCnt, samePoolCnt, normalCnt);
+    return;
+}
+
+void clearRemainCacheobj(char *argv[])
+{    
+    CACHE_OBJ_S *cacheObj = NULL;
+    CACHE_OBJ_S *volumeObj = NULL;
+    uint32_t printBufCnt = 0;
+    uint32_t remainCnt = 0;
+
+    if (0 != strcmp(argv[0], "remain"))
+    {
+        return;
+    }
+    
+    GET_NEXT_CACHE_OBJ_START(cacheObj);
+
+        volumeObj = getVolumeCacheObjIntf(cacheObj->volumeId);
+        if (NULL == volumeObj && TRUE == isObjRemain(cacheObj))
+        {
+            DBG_LogInfo(0, "clear pool:%u, vol:0x%llx", cacheObj->poolId, cacheObj->volumeId);
+            deleteCacheObj(cacheObj, clearObjCallBack, NULL);            
+            remainCnt++;
+        }
+        printBufCnt += 2;
+    GET_NEXT_CACHE_OBJ_FOR_DIAG_END(NO_CONDITITION, printBufCnt)
+
+    DBG_PrintBuf("clear obj Cnt:%u\n", remainCnt);
+    return;
+}
+
+void clearOneCacheobj(char *argv[])
+{    
+    CACHE_OBJ_S *cacheObj = NULL;
+    volumeid_t  volumeId;
+    uint32_t printBufCnt = 0;
+    int32_t ret;
+
+    if (0 != strcmp(argv[0], "one"))
+    {
+        return;
+    }
+
+    ret = cacheGetParamU64(argv[1], &volumeId);
+    if (RETURN_OK != ret)
+    {
+        DBG_Print("invalid volume id:%llu.\n", volumeId);
+        return;
+    }
+
+    GET_NEXT_CACHE_OBJ_START(cacheObj);
+
+        if (cacheObj->volumeId == volumeId)
+        {
+            if(TRUE == isObjRemain(cacheObj)) //??4:???????record???????
+            {
+                DBG_LogInfo(0, "clear one pool:%u, vol:0x%llx", cacheObj->poolId, cacheObj->volumeId);
+                 DBG_PrintBuf("clear obj Id:0x%llx\n", volumeId);
+                deleteCacheObj(cacheObj, clearObjCallBack, NULL); 
+                unlockCacheObjGlobalList();
+                break;
+            }
+            
+        }
+        printBufCnt += 2;
+    GET_NEXT_CACHE_OBJ_FOR_DIAG_END(NO_CONDITITION, printBufCnt)
+
+
+    return;
+}
+
