]> granicus.if.org Git - esp-idf/commitdiff
nvs_flash: Fix nvs_set_blob hang when partition is near to FULL
authorSagar Bijwe <sagar@espressif.com>
Tue, 21 Aug 2018 11:36:17 +0000 (17:06 +0530)
committerSagar Bijwe <sagar@espressif.com>
Tue, 21 Aug 2018 11:38:46 +0000 (17:08 +0530)
Marking a page full does not skip it from page selection process and the
same page might get returned if there is no other page with more unused
entries. Added a check for the same while storing blobs.

Fixes: https://github.com/espressif/esp-idf/issues/2313
components/nvs_flash/src/nvs_storage.cpp
components/nvs_flash/test_nvs_host/test_nvs.cpp

index 461309771769aeb0d91e380c3ecbec6b5ef869f5..3ad61667cfb34249e7aff20b919223a43c1e881f 100644 (file)
@@ -180,6 +180,9 @@ esp_err_t Storage::writeMultiPageBlob(uint8_t nsIndex, const char* key, const vo
             err = mPageManager.requestNewPage();
             if (err != ESP_OK) {
                 return err;
+            } else if(getCurrentPage().getVarDataTailroom() == tailroom) {
+                /* We got the same page or we are not improving.*/
+                return ESP_ERR_NVS_NOT_ENOUGH_SPACE; 
             } else {
                 continue;
             }
@@ -257,7 +260,6 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key
         err = findItem(nsIndex, datatype, key, findPage, item);
     }
 
-
     if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
         return err;
     }
@@ -280,6 +282,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key
         }
         /* Write the blob with new version*/
         err = writeMultiPageBlob(nsIndex, key, data, dataSize, nextStart);
+
         if (err == ESP_ERR_NVS_PAGE_FULL) {
             return ESP_ERR_NVS_NOT_ENOUGH_SPACE;
         }
index e4ab54a4ddbd94b256d7f35ceb8fefd06531d2dc..6c59f8fa0e344f8f7533be980b60f749415af666 100644 (file)
@@ -1710,6 +1710,27 @@ TEST_CASE("Check that orphaned blobs are erased during init", "[nvs]")
     TEST_ESP_OK(storage.writeItem(1, ItemType::BLOB, "key3", blob, sizeof(blob)));
 }
 
+TEST_CASE("nvs code handles errors properly when partition is near to full", "[nvs]")
+{
+    const size_t blob_size = Page::CHUNK_MAX_SIZE * 0.3 ;
+    uint8_t blob[blob_size] = {0x11};
+    SpiFlashEmulator emu(5);
+    Storage storage;
+    char nvs_key[16] = "";
+    
+    TEST_ESP_OK(storage.init(0, 5));
+
+    /* Four pages should fit roughly 12 blobs*/
+    for(uint8_t count = 1; count <= 12; count++) {
+        sprintf(nvs_key, "key:%u", count);
+        TEST_ESP_OK(storage.writeItem(1, ItemType::BLOB, nvs_key, blob, sizeof(blob)));
+    }
+    
+    for(uint8_t count = 13; count <= 20; count++) {
+        sprintf(nvs_key, "key:%u", count);
+        TEST_ESP_ERR(storage.writeItem(1, ItemType::BLOB, nvs_key, blob, sizeof(blob)), ESP_ERR_NVS_NOT_ENOUGH_SPACE);
+    }
+}
 
 TEST_CASE("Check for nvs version incompatibility", "[nvs]")
 {