[U-Boot] [PATCH] fs: fat: read: fix fat16 ls/read issue

Simon Glass sjg at chromium.org
Thu Dec 18 14:47:55 CET 2014


Hi,

On 11 December 2014 at 05:01, Przemyslaw Marczak <p.marczak at samsung.com> wrote:
> The present fat implementation ignores FAT16 long name
> directory entries which aren't placed in a single sector.
>
> This was becouse of the buffer was always filled by the
> two sectors, and the loop was made also for two sectors.
>
> If some file long name entries are stored in two sectors,
> the we have two cases:
>
> Case 1:
> Both of sectors are in the buffer - all required data
> for long file name is in the buffer.
> - Read OK!
>
> Case 2:
> The current directory entry is placed at the end of the
> second buffered sector. And the next entries are placed
> in a sector which is not buffered yet. Then two next
> sectors are buffered and the mentioned entry is ignored.
> - Read fail!
>
> This commit fixes this issue by:
> - read two sectors after loop on each single is done
> - keep the last used sector as a first in the buffer
>   before the read of two next
>
> The commit doesn't affects the fat32 imlementation,
> which works good as previous.
>
> Signed-off-by: Przemyslaw Marczak <p.marczak at samsung.com>
> Cc: Mikhail Zolotaryov <lebon at lebon.org.ua>
> Cc: Tom Rini <trini at ti.com>
> Cc: Stephen Warren <swarren at nvidia.com>
> Cc: Simon Glass <sjg at chromium.org>
> Cc: Suriyan Ramasami <suriyan.r at gmail.com>
> Cc: Lukasz Majewski <l.majewski at samsung.com>
> Cc: Wolfgang Denk <wd at denx.de>
> ---
>  fs/fat/fat.c | 33 ++++++++++++++++++++++++---------
>  1 file changed, 24 insertions(+), 9 deletions(-)

Tested-by: Simon Glass <sjg at chomium.org>

>
> diff --git a/fs/fat/fat.c b/fs/fat/fat.c
> index 04a51db..afbf12d 100644
> --- a/fs/fat/fat.c
> +++ b/fs/fat/fat.c
> @@ -823,8 +823,11 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
>         int ret = -1;
>         int firsttime;
>         __u32 root_cluster = 0;
> +       __u32 read_blk;
>         int rootdir_size = 0;
> -       int j;
> +       int j, k;

What is k? Can we use a proper variable name? Also for j. That might
save needing a comment for them.

> +       int do_read;
> +       __u8 *dir_ptr;

Why does it use __u8 instead of u8 or uint8_t for example?
>
>         if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
>                 debug("Error: reading boot sector\n");
> @@ -910,23 +913,35 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
>         }
>
>         j = 0;
> +       k = 0;
>         while (1) {
>                 int i;
>
> -               if (j == 0) {
> +               if (mydata->fatsize == 32 || !k) {
> +                       dir_ptr = do_fat_read_at_block;
> +                       k = 1;
> +               } else {
> +                       dir_ptr = (do_fat_read_at_block + mydata->sect_size);
> +                       memcpy(do_fat_read_at_block, dir_ptr, mydata->sect_size);
> +               }
> +
> +               do_read = 1;
> +
> +               if (mydata->fatsize == 32 && j)
> +                       do_read = 0;
> +
> +               if (do_read) {
>                         debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%zd\n",
>                                 cursect, mydata->clust_size, DIRENTSPERBLOCK);
>
> -                       if (disk_read(cursect,
> -                                       (mydata->fatsize == 32) ?
> -                                       (mydata->clust_size) :
> -                                       PREFETCH_BLOCKS,
> -                                       do_fat_read_at_block) < 0) {
> +                       read_blk = (mydata->fatsize == 32) ?
> +                                   mydata->clust_size : PREFETCH_BLOCKS;
> +                       if (disk_read(cursect, read_blk, dir_ptr) < 0) {
>                                 debug("Error: reading rootdir block\n");
>                                 goto exit;
>                         }
>
> -                       dentptr = (dir_entry *) do_fat_read_at_block;
> +                       dentptr = (dir_entry *)dir_ptr;
>                 }
>
>                 for (i = 0; i < DIRENTSPERBLOCK; i++) {
> @@ -951,7 +966,7 @@ int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
>
>                                         get_vfatname(mydata,
>                                                      root_cluster,
> -                                                    do_fat_read_at_block,
> +                                                    dir_ptr,
>                                                      dentptr, l_name);
>
>                                         if (dols == LS_ROOT) {
> --
> 1.9.1
>

Regards,
Simon


More information about the U-Boot mailing list