Zhiyang Zhang

mfs: working with the efficient method to get lfn in mqx 4.0

Discussion created by Zhiyang Zhang Employee on Jul 1, 2013
Latest reply on Jul 16, 2013 by Zhiyang Zhang

I tried to enumerate all the files on my sd card and get the long file names by the way through mfs using k70 with mqx 4.0.0. I just find it a rough work to get the long name of a specified file because it takes too much time.

In the _io_mfs_ioctl method, we can see the IO_IOCTL_GET_LFN' code. It disables the efficient code with #if 0 and just use MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME) to search the entire fs to find the corresponding long file name.

I tried to enable the dummy code and disable the above MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME). Using the MFS_SEARCH_PARAM variable obtained from last find file passed to ioctl() IO_IOCTL_GET_LFN, The result unexpectedly came wrong with no lfn . Something is wrong with this code or the parameter.

Then I checked the dir entries sector cached into memory, I can see that "entry_ptr" a pointer that should point to the short dir entry points to a wrong entry(points to an entry begin with 0x42 which is a tag of the end of long dir entry) .When the program goes on, the desired long dir entry pointer points to a short dir entry leading to a failed finding.Obviously it is an "off-one" issue and the parameter should be changed.

Actually, the DIR_ENTRY_INDEX in SEARCH_DATA is the next index to search and nont the current one, this can be verified in mfs_search.c line 641~645. So something need to be done to decrease the index.Note that you should store and restore the data you changed. I wrote a function MFS_Decrement_dir_index to do that and Insert it in my app.

Finally, I tried, It worked well. Worked code shows below

My app code:

                  lfn_data.PATHNAME = search_data->NAME;

                  lfn_data.LONG_FILENAME = (char_ptr)lfn;

                  lfn_data.SEARCH_DATA_PTR = search_data;

                  //store the data

                  tmp_pre_cluster = lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER;

                  tmp_cluster = lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER;

                  tmp_index = lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX;

 

 

                 //current index indicates the next directory entry, so we decrement it here

                    MFS_Decrement_dir_index(

                          &lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER, 

                          &lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX, 

                         &lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER);

 

                  error = ioctl(fs_ptr, IO_IOCTL_GET_LFN, (pointer) (&lfn_data));

                   // restore

               lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER =  tmp_pre_cluster;

                 lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER = tmp_cluster;

                 lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX = tmp_index; 

 

                 

Mfs driver code:
case IO_IOCTL_GET_LFN:            MFS_lock(file_ptr, &drive_ptr);

            {

                MFS_GET_LFN_STRUCT_PTR  lfn_ptr = ((MFS_GET_LFN_STRUCT_PTR) param_ptr);

                char_ptr pathname = MFS_Parse_Out_Device_Name(lfn_ptr->PATHNAME);

#if 0

                result = MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME);

#endif

 

#if 1          //change from 0 to1
                //            _mfs_error result;
                MFS_DIR_ENTRY_PTR       entry_ptr;

                if ( lfn_ptr->SEARCH_DATA_PTR )
                {
                    entry_ptr =
                        MFS_Read_directory_sector(drive_ptr,lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER,
                        INDEX_TO_SECTOR(lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX), &result);
                    if ( (result== MFS_NO_ERROR && entry_ptr!=NULL) )
                    {                                                              
                        entry_ptr += INDEX_TO_OFFSET (lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX) ;

                        result = MFS_get_lfn_of_entry(drive_ptr,entry_ptr,
                            lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER,
                            lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX ,
                            lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER,
                            lfn_ptr->LONG_FILENAME);

 

                                            }

                }
                else
                {
                    result = MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME);
                }

}

 

MFS_Decrement_dir_index() implementation is below

/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Decrement_dir_index
* Returned Value   :  uint_32 error_code
* Comments  :
*END*---------------------------------------------------------------------*/

_mfs_error  MFS_Decrement_dir_index
    (
    uint_32_ptr    cluster_ptr,         /*[IN/OUT]  the initial/next cluster # */
    uint_32_ptr    index_ptr,           /*[IN/OUT]  the initial/next index */
    uint_32_ptr    prev_cluster_ptr     /*[IN/OUT]  the prev cluster # */
    )
{
    uint_32        index;
    uint_32        cluster;
    _mfs_error     error_code;

    error_code = MFS_NO_ERROR;
    index   = *index_ptr;
    cluster = *cluster_ptr;

 

    if(0 == index)
    {
             if (  *prev_cluster_ptr != 0 )
             {
                    //restore prev cluster to current cluster
                    cluster = *prev_cluster_ptr;
                    index = 127;
             
             }
             else
             {
                    error_code = MFS_INVALID_CLUSTER_NUMBER;

                    return error_code;
             } 
    }
    else
    {
          index --;
    }
   
    if ( (cluster != *cluster_ptr)  )
    {
             if ( prev_cluster_ptr != NULL )
             {
                 *prev_cluster_ptr = 0; //now *prev_cluster_ptr set to 0
             }
    }
    //error is here when index is 138 ,above does not executed and wrongly increased

    *index_ptr   = index;
    *cluster_ptr = cluster;

    return(error_code);
}

 

#endif

 

 

 

 

 

Test result:

 

Sample: 27 directories and 803 files, directory depth is 4.

 

Currently time cost
Only SLN              SLN&LFN
216ms                   275ms

Previously the time
Only SLN              SLN&LFN
216ms                   751ms

Outcomes