--- ./source/private_module/spa/node_mgr/nmgr_io.c	2018-02-09 13:47:03.000000000 +0000
+++ ./source/private_module/spa/node_mgr/nmgr_io.c.hotpatch	2021-11-24 07:23:29.000000000 +0000
@@ -335,7 +335,7 @@
     IOD_ADD_STARTQ(childReq);
     return RETURN_OK;
 }
-
+bool checkFreergnNeedReadRetry(REQ_S *req);
 /**************************************************************************
      :  дsegmentɺ
  :  req - дREQ
@@ -367,7 +367,7 @@
     ret = genReqDone(req);
     return ret;
 }
-
+void startFreergnReadRetry(REQ_S *req);
 /**************************************************************************
      :  дsegmentREQ childDone 
  :  selfReq  - REQָ 
@@ -384,25 +384,25 @@
         GEN_REQ_COPY_ERROR(selfReq, childReq);
         if ((OP_READ_THROUGH == selfReq->opCode) && (RETURN_CKG_NEED_RETRY_READ == childReq->result))
         {
-            /* need_retry룬ǳcrc󣬵ȴϲͳһ */
             NMGR_REQ_SET_ERR_CODE(selfReq, RETURN_META_DATA_CRC_ERROR);
         }
     }
     else if ((OP_READ == selfReq->opCode) || (OP_READ_THROUGH == selfReq->opCode))
-    {        
+    {
         selfReq->sgl = childReq->sgl;
     }
-
     REQ_DELETE(childReq);
-    
+    if (checkFreergnNeedReadRetry(selfReq))
+    {
+        startFreergnReadRetry(selfReq);
+        return;
+    }
     if (atomic_dec_and_test(&selfReq->notBackNum))
     {
         IOD_ADD_DONEQ(selfReq);
     }
-
     return ;
 }
-
 /**************************************************************************
      :  дڵ
  :  nodeInst    - ڵĽڵ
@@ -3277,3 +3277,167 @@
 }
 /* SPA end */
 
+void calcFreeRgnRangeNew(NMGR_SEG_HDR_S *segHdr, 
+                         uint64_t       *outLba, 
+                         uint32_t       *outLen)
+{
+    uint64_t lba;
+    uint32_t len;
+    uint32_t freeRgnOffset;
+
+    if (NMGR_LAYOUT_VERSION_ADDFREERGN <= segHdr->version)
+    {
+        freeRgnOffset = segHdr->pendFreeRgnIdx * segHdr->freeRgnNPage;
+        lba = ((uint64_t)NMGR_SEG_HDR_DISK_SIZE_IN_PAGE + freeRgnOffset) * NMGR_PAGE_SIZE_IN_SEC;
+    }
+    else
+    {
+        lba = (uint64_t)NMGR_SEG_HDR_DISK_SIZE_IN_PAGE * NMGR_PAGE_SIZE_IN_SEC;
+    }
+    
+    len = segHdr->freeRgnNPage * NMGR_PAGE_SIZE_IN_SEC;
+    
+    *outLba = lba;
+    *outLen = len;
+    return;
+}
+
+uint32_t genFreeRgnCrcNew(SGL_S *sgl)
+{
+    uint32_t crc;
+    int32_t  ret;
+    
+    if (0 == sgl->entrySumInChain)
+    {
+        return NMGR_INVALID_CRC;
+    }
+
+    ret = createSglCrc32IgnoreDif(sgl, 0, (PAGE_SIZE_4K * sgl->entrySumInChain), &crc);
+    if (RETURN_OK != ret)
+    {
+        crc = NMGR_INVALID_CRC;
+    }
+    
+    return crc;
+}
+
+bool checkFreergnNeedReadRetry(REQ_S *req)
+{
+    uint64_t        lba;
+    uint32_t        len;
+    uint32_t        calCrc;
+    bool            condition = FALSE;
+    NMGR_SEG_HDR_S  *segHdr   = NULL;
+
+    if (req->result != RETURN_OK)
+    {
+        return FALSE;
+    }
+
+    if ((req->opCode != OP_READ) && (req->opCode != OP_READ_THROUGH))
+    {
+        return FALSE;
+    }
+    
+    if (req->parent == NULL)
+    {
+        return FALSE;
+    }
+
+    if ((req->parent->opCode != NMGR_INNER_OPCODE_ALLOC_FROM_FREERGN) &&
+        (req->parent->opCode != NMGR_INNER_OPCODE_FREE_NODES_TO_ONE_SEG))
+    {
+        return FALSE;
+    }
+
+    segHdr = NMGR_REQ_GET_SEGHDR(req->parent);
+    if (segHdr == NULL)
+    {
+        return FALSE;
+    }
+
+    if (segHdr->magic != NMGR_SEG_HDR_MAGIC)
+    {
+        return FALSE;
+    }
+
+    /* ֧ѭдİ汾У */
+    if (segHdr->version < NMGR_LAYOUT_VERSION_ADDFREERGN)
+    {
+        return FALSE;
+    }
+
+    /* countΪ0ʱfreeRgnû, ˲У */
+    if (segHdr->freeRgn.pendNodeCount == 0)
+    {
+        return FALSE;
+    }
+
+    calcFreeRgnRangeNew(segHdr, &lba, &len);
+
+    /* ǷfreeRgn */
+    condition = ((req->objectId == segHdr->segId) && 
+                 (req->objectLba == lba) && 
+                 (req->length == len) && 
+                 (req->sgl->entrySumInChain == segHdr->freeRgnNPage));
+    if (condition)
+    {
+        /* У鲻ͨʱtrue */
+        calCrc = genFreeRgnCrcNew(req->sgl);
+        if (segHdr->pendQueueCrc != calCrc)
+        {
+            SPA_LIMIT_PRINT_ERROR(NO_LOGID, "Check free rgn failed, volId(0x%llx), objId(0x%llx), "
+                                  "len(%u), parentOp(%u), opCode(%u), times(%u), freeRgnIdx(%u).",
+                                  req->volumeId, req->objectId, req->length, 
+                                  req->parent->opCode, req->opCode, 
+                                  req->readThroughTimes, segHdr->pendFreeRgnIdx);
+            return TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+void startFreergnReadRetry(REQ_S *req)
+{
+    NODE_MGR_S *nodeInst = NULL;
+
+    /* ͷSGL */
+    if (req->sgl != NULL)
+    {
+        FREE_PAGES_AND_SGL(req->volumeId, req->objectId, 
+                       req->sgl, PAGE_USAGE_NODEMGR_READ);
+        req->sgl = NULL;
+    }
+
+    if (req->readThroughTimes < 4)
+    {
+        /*  */
+        nodeInst = NMGR_REQ_GET_NMGR(req);
+        incRwSegBackStats(req, nodeInst->segType, req->opCode, req->result);
+
+        /* ͸ */
+        req->opCode = OP_READ_THROUGH;
+        req->readThroughTimes++;
+
+        IOD_ADD_STARTQ(req);
+        return;
+    }
+
+    SPA_LIMIT_PRINT_ERROR(NO_LOGID, "Free rgn read through failed, maxTimes(%u), "
+                          "volId(0x%llx), objId(0x%llx), len(%u).",
+                          req->readThroughTimes, req->volumeId, 
+                          req->objectId, req->length);
+
+    /* ﵽ͸, ʧ */
+    req->result = RETURN_META_DATA_CRC_ERROR;
+    NMGR_REQ_SET_ERR_CODE(req, RETURN_META_DATA_CRC_ERROR);
+
+    if (atomic_dec_and_test(&req->notBackNum))
+    {
+        IOD_ADD_DONEQ(req);
+    }
+
+    return;
+}
+
--- ./source/private_module/spa/node_mgr/nmgr_seg_layout.c	2018-02-09 13:47:03.000000000 +0000
+++ ./source/private_module/spa/node_mgr/nmgr_seg_layout.c.hotpatch	2021-11-24 07:23:29.000000000 +0000
@@ -698,14 +698,16 @@
     NMGR_SEG_HDR_S      *segHdr   = NULL;
     NMGR_NODE_REQ_S     *nodeReq  = NULL;
     int32_t              ret      = MS_COND_STATUS_FALSE;
-    
+    int32_t              errNo;
     nodeReq  = NMGR_REQ_GET_NODE_REQ(req);
     segHdr   = nodeReq->segHdr;
-    
-    /* ǽڵѻȡĽڵ㴦ֱӷFALSEü */
     NMGR_NODE_REQ_GOT_ENOUGH(nodeReq, MS_COND_STATUS_FALSE);
-
-    spin_lock(&segHdr->lock);    
+    errNo = NMGR_REQ_GET_ERR_CODE(req);
+    if (errNo == RETURN_META_DATA_CRC_ERROR || req->result == RETURN_META_DATA_CRC_ERROR)
+    {
+        return MS_COND_STATUS_FALSE;
+    }
+    spin_lock(&segHdr->lock);
     switch(condition)
     {
         case MS_COND_IF_SEG_FREECNT_NOT_ZERO:
@@ -714,14 +716,12 @@
                 ret = MS_COND_STATUS_TRUE;
             }
             break;
-
         case MS_COND_IF_SEG_HAS_NODES:
             if (segHdr->pendAllocedNum < segHdr->maxNodeNum)
             {
                 ret = MS_COND_STATUS_TRUE;
             }
             break;
-
         default:
             DBG_LogError(NODE_MGR_ID_015E, "Condition(%u) is invalid.", condition);
             ret = MS_COND_STATUS_ERROR;
