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

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

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

1,463 次查看
zhiyangzhang
Contributor III

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

标签 (1)
标记 (6)
2 回复数

848 次查看
fukefeng
Contributor III

        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);

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

#if 1

                //            _mfs_error result;

                MFS_DIR_ENTRY_PTR       entry_ptr;

  uint_32 tmp_pre_cluster, tmp_cluster, tmp_index;

  tmp_pre_cluster = lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER;

  tmp_cluster = lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER;

  tmp_index = lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX;

               MFS_Decrement_dir_index(

  &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);

                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);

                }

  lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER = tmp_pre_cluster;

  lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER = tmp_cluster;

  lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX = tmp_index;

#endif

            }

            MFS_unlock(drive_ptr,FALSE);

            break;

maybe we can modify the driver code like this, so we don't need to modify the app code. thank you for save the lfn problem.

848 次查看
zhiyangzhang
Contributor III

Of course it works. But we expect the new patch of the dummy code. I patched the dummy code firstly in this way but then moved it to app because it would not affect others or in other words it is not sure that the dummy code is incorrect. So just make it in app will be more compatible with others and wait the mqx patch or new release.