Hi Everyone,

As far as I noticed, set_cluster can be called quite often with a size being 
zero. That can indeed be with a file that has a size being an exact multiple 
(including 0) of the clustersize, but also for files that are smaller than the 
size of one cluster. In that case, the 1st call to set_cluster has a size being 
zero:

> fatwrite mmc 0:1 42000000 test3 200
writing test3
set_cluster; clustnum: 1487, startsect: 6104, size 0
set_cluster; clustnum: 1487, startsect: 6104, size 512
set_cluster; clustnum: -6, startsect: 132, size 2048
512 bytes written

This was solved by adding the "if(size)" in set_cluster (otherwise the above 
test would fail). However: this does not solve all the problems. If I tried to 
write a file of 16 bytes, I still got an error. Looking closer at set_cluster, 
the 1st call to disk_write( ) has a size being "size / mydata->sect_size". This 
would mean that for any file (or file remainder) smaller than the sector size 
(typicaly 512 bytes), the fatwrite would fail.

So to my opinion, the actual cause of the problem is in the function 
"disk_write( )", that can't be called with a size being zero. That could be 
solved by adding tests before calling set_cluster and/or before calling 
disk_write from set_cluster, but the safest (and simplest) would be to add this 
piece of code to disk_write:

        if(nr_blocks == 0) {
                return 0;
        }

With this change I have been able to write various file sizes so far without 
problems (512 bytes, 2048, 2049, 16, 0). 

Another option would be to solve this in the cur_dev->block_write function, 
being mmc_bwrite( ) for the mmc device. Since his has a do { } while, it will 
always call mmc_write_blocks() even if blkcnt equals zero. Maybe even the 
mmc_write_blocks would be the best place to fix this...

I will do some further testing here. Meanwhile, please let me know if this 
change would make sense to you, and what would be the best place to put it. 
Probably the lowest level function, if you would ask me.
Also I would like to know if it would not cause any oher problems according to 
your knowledge.

Regards,

Ruud

-----Oorspronkelijk bericht-----
Van: Benoît Thébaudeau [mailto:benoit.thebaud...@advansee.com] 
Verzonden: vrijdag 12 april 2013 23:18
Aan: Tom Rini
CC: Ruud Commandeur; u-boot@lists.denx.de; Mats K?rrman
Onderwerp: Re: [U-Boot] fatwrite problem

Hi Tom,

On Friday, April 12, 2013 10:42:34 PM, Tom Rini wrote:
> On Fri, Apr 12, 2013 at 09:39:19PM +0200, Beno??t Th??baudeau wrote:
> > Hi Tom, Ruud, Mats,
> > 
> > On Friday, April 12, 2013 5:12:31 PM, Tom Rini wrote:
> > > On Fri, Apr 12, 2013 at 05:06:35PM +0200, Ruud Commandeur wrote:
> > > > Hi Mats,
> > > > 
> > > > Thanks a lot, this seems to solve my problem. Nothing more actualy than
> > > > adding a "if(size)" around the code block of set_sector( ). I could
> > > > have
> > > > thought of that myself, but was not sure if anything else should be
> > > > done
> > > > in this case...
> > > 
> > > Since your change sounds slightly different, can you confirm that it
> > > also solves the problem and if so post it as patch with Signed-off-by
> > > and so forth?  Thanks!
> > > 
> > > > 
> > > > Regards,
> > > > 
> > > > Ruud
> > > > 
> > > > -----Oorspronkelijk bericht-----
> > > > Van: Mats K?rrman [mailto:mats.karr...@tritech.se]
> > > > Verzonden: vrijdag 12 april 2013 16:11
> > > > Aan: Ruud Commandeur
> > > > CC: u-boot@lists.denx.de
> > > > Onderwerp: RE: fatwrite problem
> > > > 
> > > > Hi Ruud,
> > > > 
> > > > Ruud Commandeur wrote:
> > > > > Once the size of the set_cluster call equals 0, the mmc command is
> > > > > incomplete and times out. In the earlier reported problem, a patch is
> > > > > mentioned, but not available for dowload here. Also in the latest
> > > > > versions of the git repository I could not find a patch for this
> > > > > problem. Can anyone tell me if there is a fix for this problem?
> > > > 
> > > > I asked Damien Huang (back then) and got the following reply (I think
> > > > there
> > > > was
> > > > some character encoding problem so his mail never was accepted by the
> > > > list).
> > > > I have not further analyzed the contents, anyway it wasn't the solution
> > > > to
> > > > my problem.
> > > > BR // Mats
> > > > 
> > > > Damien Huang wrote:
> > > > As requested from Mats, I am resending this email. The patch is given
> > > > below:
> > > > 
> > > > diff -cr ./u-boot-original/u-boot/fs/fat/fat_write.c
> > > > ./u-boot-test/u-boot/fs/fat/fat_write.c
> > > > *** ./u-boot-original/u-boot/fs/fat/fat_write.c    2013-02-07
> > > > 14:47:33.314732999 +1100
> > > > --- ./u-boot-test/u-boot/fs/fat/fat_write.c    2013-02-28
> > > > 15:36:24.551861920 +1100
> > > > ***************
> > > > *** 562,596 ****
> > > >   {
> > > >       int idx = 0;
> > > >       __u32 startsect;
> > > > !
> > > > !     if (clustnum > 0)
> > > > !         startsect = mydata->data_begin +
> > > > !                 clustnum * mydata->clust_size;
> > > > !     else
> > > > !         startsect = mydata->rootdir_sect;
> > > > !
> > > > !     debug("clustnum: %d, startsect: %d\n", clustnum, startsect);
> > > > !
> > > > !     if (disk_write(startsect, size / mydata->sect_size, buffer) < 0)
> > > > {
> > > > !         debug("Error writing data\n");
> > > > !         return -1;
> > > > !     }
> > > > !
> > > > !     if (size % mydata->sect_size) {
> > > > !         __u8 tmpbuf[mydata->sect_size];
> > > > !
> > > > !         idx = size / mydata->sect_size;
> > > > !         buffer += idx * mydata->sect_size;
> > > > !         memcpy(tmpbuf, buffer, size % mydata->sect_size);
> > > > !
> > > > !         if (disk_write(startsect + idx, 1, tmpbuf) < 0) {
> > > > !             debug("Error writing data\n");
> > > > !             return -1;
> > > > !         }
> > > > !
> > > > !         return 0;
> > > > !     }
> > > > !
> > > >       return 0;
> > > >   }
> > > >  
> > > > --- 562,595 ----
> > > >   {
> > > >       int idx = 0;
> > > >       __u32 startsect;
> > > > !     if(size) //if there are data to be set
> > > > !     {
> > > > !         if (clustnum > 0)
> > > > !             startsect = mydata->data_begin +
> > > > !                     clustnum * mydata->clust_size;
> > > > !         else
> > > > !             startsect = mydata->rootdir_sect;
> > > > !
> > > > !         debug("clustnum: %d, startsect: %d\n", clustnum, startsect);
> > > > !
> > > > !         if (disk_write(startsect, size / mydata->sect_size, buffer) <
> > > > 0)
> > > > {
> > > > !             debug("Error writing data\n");
> > > > !             return -1;
> > > > !         }
> > > > !
> > > > !         if (size % mydata->sect_size) {
> > > > !             __u8 tmpbuf[mydata->sect_size];
> > > > !
> > > > !             idx = size / mydata->sect_size;
> > > > !             buffer += idx * mydata->sect_size;
> > > > !             memcpy(tmpbuf, buffer, size % mydata->sect_size);
> > > > !
> > > > !             if (disk_write(startsect + idx, 1, tmpbuf) < 0) {
> > > > !                 debug("Error writing data\n");
> > > > !                 return -1;
> > > > !             }
> > > > !         }
> > > > !     }//end if data to be set
> > > >       return 0;
> > > >   }
> > > >  
> > > > diff -cr ./u-boot-original/u-boot/include/configs/am335x_evm.h
> > > > ./u-boot-test/u-boot/include/configs/am335x_evm.h
> > > > *** ./u-boot-original/u-boot/include/configs/am335x_evm.h    2013-02-07
> > > > 14:47:35.754702325 +1100
> > > > --- ./u-boot-test/u-boot/include/configs/am335x_evm.h    2013-03-01
> > > > 12:25:23.942104474 +1100
> > > > ***************
> > > > *** 143,148 ****
> > > > --- 143,149 ----
> > > >   #define CONFIG_CMD_MMC
> > > >   #define CONFIG_DOS_PARTITION
> > > >   #define CONFIG_FS_FAT
> > > > + #define CONFIG_FAT_WRITE
> > > >   #define CONFIG_FS_EXT4
> > > >   #define CONFIG_CMD_FAT
> > > >   #define CONFIG_CMD_EXT2
> > > 
> > > Benoit, what do you think?  Thanks!
> > 
> > This is fine as a workaround, but it does not fix the root cause of the
> > issue:
> > set_clusster() should not have been called with size set to 0 in the first
> > place. This is hiding some cluster mishandling. It may mean that a cluster
> > is
> > wasted at EoF in some cases, which is unexpected and may trigger abnormal
> > behaviors on systems reading back those files.
> > 
> > What kind of action triggered this issue for you:
> >  - writing an empty file?
> >  - writing a file with a size equal to an integer multiple of the cluster
> >  size?
> >  - something else?
> > 
> > This can be caused only be lines 713, 724 or 739. Looking closer at the
> > code,
> > only line 713 triggers this issue, so an 'if' could be added here rather
> > than in
> > set_cluster().
> > 
> > The code for writing an empty file is broken: It should set both the start
> > cluster and the size to 0 in the corresponding directory entry, but it
> > actually
> > allocates a single cluster (see find_empty_cluster() called from
> > do_fat_write()).
> > 
> > So 2 fixes are required here:
> >  - 'if' either in set_cluster(), or on line 713 to discard empty sizes, or
> >  make
> >    the underlying MMC driver return without doing anything if size is 0,
> >    the
> >    latter being perhaps the most robust solution if it does not cause other
> >    issues for this driver,
> 
> I prefer updating set_cluster since he sees this in one MMC driver and I
> in another (meaning we would have to go whack all of them, or start
> poking drivers/mmc/mmc.c).  I can confirm that size != 0 in that test
> fixes the problem here.

OK.

> >  - empty file creation.
> 
> I took a stab at this and ended up killing my test FAT partition, which
> is not a big deal, but can you take a stab at this please?  Thanks!

OK, but I can't guarantee when.

Best regards,
Benoît
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to