This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

fds_record_update sometimes always returns FDS_ERR_NO_SPACE_IN_FLASH

Hi,

I'm using FDS instead of pstorage. FDS version is SDK13.0.0. fds_record_update sometimes always returns FDS_ERR_NO_SPACE_IN_FLASH though I call fds_gc after it gets FDS_ERR_NO_SPACE_IN_FLASH every time.

static void fds_evt_handler(fds_evt_t const * const p_fds_evt)
{
    if (p_fds_evt->result != FDS_SUCCESS) {
        NRF_LOG_RAW_INFO("FDS_FAILURE %d\r\n", p_fds_evt->result);
        return;
    }

    switch (p_fds_evt->id)
    {
        case FDS_EVT_INIT:
            NRF_LOG_RAW_INFO("FDS_EVT_INIT\r\n");
            m_fstorage_operating = false;
            break;
        case FDS_EVT_WRITE:
            NRF_LOG_RAW_INFO("FDS_EVT_WRITE\r\n");
            m_fstorage_operating = false;
            break;
        case FDS_EVT_UPDATE:
            NRF_LOG_RAW_INFO("FDS_EVT_UPDATE\r\n");
            m_fstorage_operating = false;
            break;
        case FDS_EVT_DEL_RECORD:
           NRF_LOG_RAW_INFO("FDS_EVT_DEL_RECORD\r\n");
            m_fstorage_operating = false;
            break; 
        case FDS_EVT_DEL_FILE:
            NRF_LOG_RAW_INFO("FDS_EVT_DEL_FILE\r\n");
            m_fstorage_operating = false;
            break;
        case FDS_EVT_GC:
            NRF_LOG_RAW_INFO("FDS_EVT_GC\r\n");
            m_fstorage_operating = false;
        default:
            break;
    }
    NRF_LOG_FLUSH();

}

void sf_fstorage_garbage_collection()
{
    ret_code_t ret;
    m_fstorage_operating = true;

    NRF_LOG_RAW_INFO("sf_fstorage_garbage_collection\r\n");
    ret = fds_gc();
    if (ret != FDS_SUCCESS) {
        NRF_LOG_RAW_INFO("fds_gc error ret %d \r\n", ret);
    }

    while(m_fstorage_operating) {
        uint32_t err_code = sd_app_evt_wait();
        app_sched_execute();
        APP_ERROR_CHECK(err_code);
    }
    NRF_LOG_RAW_INFO("fds_gc success \r\n");
    NRF_LOG_FLUSH();
}

static void sf_print_fds_stat()
{
    fds_stat_t p_stat;
    fds_stat(&p_stat);
    _print_info("open_records   : %d\r\n", p_stat.open_records);
    _print_info("valid_records:    %d\r\n", p_stat.valid_records);
    _print_info("dirty_records:    %d\r\n", p_stat.dirty_records);
    _print_info("words_reserved: %d\r\n", p_stat.words_reserved);
    _print_info("words_used      : %d\r\n", p_stat.words_used);
    _print_info("largest_contig   : %d\r\n", p_stat.largest_contig);
    _print_info("freeable_words  : %d\r\n", p_stat.freeable_words);
}

void update_data(void)
{
  ret_code_t ret = fds_record_update(p_record_desc, &record);
  NRF_LOG_RAW_INFO("update already exist record. %d \r\n", p_record_desc->record_id);
    sf_print_fds_stat();
  while(ret == FDS_ERR_NO_SPACE_IN_FLASH)
  {
        NRF_LOG_RAW_INFO("RUN GARBAGE COLLECTION\r\n");
        sf_fstorage_garbage_collection();
          sf_print_fds_stat();
        m_fstorage_operating = true;
        ret = fds_record_update(p_record_desc, &record);
          sf_print_fds_stat();
   }
}

It makes sense to get the error every time, but it gets the error sometimes. Do you know the cause?

[2017/11/16 0:15] add sf_print_fds_stat() function. attach log file.FDS_GC_ERROR3_REPRODUCED.log

Best Regards, Haruki

  • I know what fragmentation is, my question was more like what do you mean by "I think this is fragmentation".

    If those are the records you store 2048 words should be enough, so FDS_VIRTUAL_PAGES should be enough, but please try to increase it and see if that makes any difference.

    fds_gc() should make the records compact.

    What largest_contig do you get? Have you tried to print it several time to see its development when you store and update records? Does it change before and after fds_gc()? (Remember to wait for FDS_EVT_GC)

    See this for how much Peer Manager uses.

    You can also try to look into the data that is actually stored in flash, and try to decode what is actually going on there.

  • I mean the cause is fragmentation.

    I edited my question.

    I added fds_stat log function and attached my log file. Please look below line 13349 in the file.

    After "RUN GARBAGE COLLECTION", largest_contig is 196 and freeable_words is 0. But the size of data to be stored is 197 words. So it can't be stored ever. If fds_gc() make the records compact, the largest_contig must be 2048 words - (147 words*7 + 39 words + 176 words + 26 words + 197 words) = 581 words, isn't it?

    I know how much Peer Manager uses. What I want to know is how many records Peer Manager uses.

  • It is not that simple. In the first page you have 1024 words.The first two words is the page tag. 1022 left.Then let us say you store the 7 of the 147 word records:

    1022-147 = 875

    875-147 = 728

    728-147 = 581

    581-147 = 434

    434-147 = 287

    287-147 = 140

    The last record doesn't fit in this page, so it will be stored in second page. The first two words is the page tag. 1022 left.

    1022-147 = 875

    Then let us say you store 1 of the 39 word record (I'm not a 100% sure if this will be store in the last 140 bytes of the first page):

    875-39 = 836

    Then let us say you store 2 of the 176 word records:

    836-176 = 660

    660-176 = 484

    Then let us say you store 1 of 197 word record:

    484-197 = 287

    Then let us say you store 1 of 40? word bond record:

    287-40 = 247

    Yes, this is more than 196 from fds_stat(), but it is pretty close. I don't know the order of your record, but 196 could be correct.

  • 7*147 + 39 + 2 * 176 + 197 + 40 = 1657

    "These are stored in separate records, each with a header of 3 words."

Related