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

Reply Children
Related