[syslinux] [PATCH 1/5] fat: fix minfatsize for large FAT32

Pete Batard
2016-02-26T12:51:55Z

Hi Ady,

I won't comment on the reasons why the original computation was wrong,
but thanks for the detailed analysis.

On 2016.02.26 08:05, Ady via Syslinux wrote:
>> Thus we can finally get a formula for Fs that satisfies the above:
>>
>>      Fs = (To - Rs + Nf * Cs)  / ((Ss * Cs / Fe) + Nf) + 1
>
> I believe such formula is slightly inaccurate too.
>
> My resulting inequation is
>
>          ( To - Rs ) + ( 2 * Cs )
>   Fs >= __________________________
>           ( Ss * Cs / Fe ) + Nf
>

I believe you're right. I assumed that the 2 that eventually ends up in
the numerator was the Number of FATs, but looking further, and
especially at Wikipedia [1], I see that it is the number of special
clusters, which is fixed to 2 regardless of the number of FATs:

"The first two entries in a FAT store special values: The first entry
(cluster 0 in the FAT) holds the FAT ID (...) The second entry (cluster
1 in the FAT) nominally stores the end-of-cluster-chain marker (...)"

So as you point out, this should be hardcoded to 2. Thanks for picking
this up.

Wouldn't have been a dramatic mistake, since I don't see any possibility
of using a number of FATs that's anything but 2 in the context of Rufus,
but we should indeed get our variables right.

> instead of _always_ adding "+1" (which would be
> incorrect and inefficient from the point of view of the resulting
> allocatable size).

I carefully considered this, and I dispute the fact that this is incorrect.

The problem is we're dealing with a fraction, which will be limited by
the number of bits the computer uses to store the data *and might be
rounded down behind the scenes*. E.g. unless you use a crazy number of
bits to store your numbers, something like (10^100 + 1) / (10^100) will
produce 1 and the modulo (10^100 + 1) % (10^100) will produce 0. So if
you use the modulo to figure out if you need to round up, you're going
to miss some cases. And while I'd like to believe that all of
"roundup",
"ceiling" and friends are smart enough to know the precision
they're
dealing with, and compensate accordingly, or, more realistically here,
that the numbers we're dealing with in this case will never be large
enough to test the limits of our precision (especially our numerator and
denominator are set to 64bit and our disks will never be larger than 2TB
anyway, because FAT32), I'd rather not take any risks here, even more so
as I am fixing code that was missing addressable sectors and the last
thing I'd want is find out that, because of a dodgy rounding or a wrong
assumption, we might still end up missing some sectors after all.

And yeah, we could add the actual roundup in the equations themselves (I
actually did that when I was trying to figure out if the original wrong
computation wasn't due to the roundup), but since the "only going to be
*very slightly* wasteful in an exceedingly limited set of cases" +1 is a
safe and sure way to address the rounding "issue", I have to admit
that
I'm not that interested in trying to come up with a more mathematically
satisfying solution.

Working and relatively efficient code is what I am after, and as far as
I'm concerned, using +1 is both a "correct" and
"efficient" way of
achieving that.

Still, I won't prevent you (or anybody else interested) to provide a
proper formula if you want. ;)

Regards,

/Pete

[1]