Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Unable to return from fds_gc(), stuck in infinite loop.

There is a bug in fds.c file, Please go through the below code snippet.

ret_code = fds_record_update(&desc, record_id);
if (ret_code == FDS_ERR_NO_SPACE_IN_FLASH)
{
            ret_code = fds_gc();
            ERROR_CHECK(ret_code);
            ret_code = fds_record_update(&desc, record_id);
 }

I do not return from fds_gc(), execution stays there for infinite. 

More information:

1) #define FDS_VIRTUAL_PAGES 30

2) #define FDS_VIRTUAL_PAGE_SIZE (1024)

3) Initialization is successful and able to write, update and read several records.

4) SDK version: nRF_SDK_15.2.0

The problem occurs when record_update is failed with FDS_ERR_NO_SPACE_IN_FLASH and followed by garbage collection function fds_gc().

According to me, a library function has to return an error code if something is wrong, but not locked in an infinite loop. This is a serious bug.

Please help me as I am stuck in the crucial phase of our development.

Regards,

Jagadeep

Parents
  • I missed an important information.

    The event handler is not called with FDS_EVT_GC event after called fds_gc().  Please find the updated event handler function and code using FDS functions.

    static void fds_evt_handler(const fds_evt_t* p_evt)
    {
        switch (p_evt->id)
        {
            case FDS_EVT_INIT:
            {
                if (p_evt->result == FDS_SUCCESS)
                {
                    m_fds_initialized = 1;
                    NRF_LOG_INFO("Event: Init");
                }
                break;
            }
            case FDS_EVT_WRITE:
            {
                if (p_evt->result == FDS_SUCCESS)
                {
                    write_done = 1;
                    NRF_LOG_INFO("Event: Write");
                }
                break;
            }
            case FDS_EVT_DEL_RECORD:
            {
                if (p_evt->result == FDS_SUCCESS)
                {
                    erase_done = 1;
                    NRF_LOG_INFO("Event: Delete");
                }
                break;
            }
            case FDS_EVT_UPDATE:
            {
                if (p_evt->result == FDS_SUCCESS)
                {
                    update_done = 1;
                    NRF_LOG_INFO("Event: Update");
                }
                break;
            }
            case FDS_EVT_GC:
                if (p_evt->result == FDS_SUCCESS)
                {
                    gc_done = 1;
                    NRF_LOG_INFO("Event: Garbage Collection");
                }
                break;
            default:
                break;
        }
    }
    
    static void wait_for_fds_ready(void)
    {
        while (!m_fds_initialized)
        {
            __WFE();
        }
    }
    
    static void wait_for_write_done(void)
    {
        while (!write_done)
        {
            __WFE();
        }
        write_done = 0;
    }
    
    static void wait_for_update_done(void)
    {
        while (!update_done)
        {
            __WFE();
        }
        update_done = 0;
    }
    
    static void wait_for_gc_done(void)
    {
        while (!gc_done)
        {
            __WFE();
        }
        gc_done = 0;
    }
    
    void write_event()
    {
       ret_code = fds_record_find(record_id->file_id, record_id->key, &desc, &tok);
        /* Write only when file is not found */
        if (ret_code == FDS_ERR_NOT_FOUND)
        {
            ret_code = fds_record_write(&desc, record_id);
            if (ret_code == FDS_SUCCESS)
            {
                wait_for_write_done();
            }
            else if (ret_code == FDS_ERR_NO_SPACE_IN_FLASH)
            {
                ret_code = fds_gc();
                wait_for_gc_done();
                ERROR_CHECK_HIGH(ret_code);
                ret_code = fds_record_write(&desc, record_id);
                wait_for_write_done();
            }
        }
        else if (ret_code == FDS_SUCCESS)
        {
            /* Write the updated record to flash. */
            ret_code = fds_record_update(&desc, record_id);
            if (ret_code == FDS_SUCCESS)
            {
                wait_for_update_done();
            }
            else if (ret_code == FDS_ERR_NO_SPACE_IN_FLASH)
            {
                ret_code = fds_gc();
                wait_for_gc_done();
                ERROR_CHECK_HIGH(ret_code);
                ret_code = fds_record_update(&desc, record_id);
                wait_for_update_done();
            }
            else
            {
                ERROR_CHECK_HIGH(ret_code);
            }
        }
    }

  • Hello,

    Terje is currently out travelling.

    I was wondering if you experience on_operation_failure() occurs here, this will be triggered by NRF_EVT_FLASH_OPERATION_ERROR in fs_sys_event_handler().

    Best regards,
    Kenneth

  • Hello,

    I experienced a similar issue as Jagadeep Ram. It's not when I call fds_gc() on my case, but I got stuck on the same loop, where queue_has_next() return true, but FDS_OP in NONE and never get out of the loop !

    About Kenneth suggestion to check fs_sys_event_handler(), I don't understand it. Is this function still called in SDK 15.2 ? I was thinking it was part of fstorage module.

    On SDK15, on_operation_failure() is called inside nrf_fstorage_sd module and never hit on my case.

  • Can you provide an example we may run here to recreate it?

    Best regards,
    Kenneth

  • Hi Kenneth

    I also met the issue that fds_gc() would be stuck in SDK 15.3.0_59ac345.

    Would it be possible for you to tell me if this problem has been solved or not?

    Look forward to hearing from you soon.

    Sincerely

    Bevin 

Reply Children
No Data
Related