size number precision problems
Hi. I'm using genimage 16 (Debian) and have run into a spot of trouble with large numbers, eg
ERROR: Invalid size suffix '.0G' in '2.0G'
I start with a static genimage template containing some tags. After calculating on-disk sizes I run the template through sed to populate the tags with real numbers which are formatted using numfmt --to=si. For example:
image rootA.ext4 {
exec-post = "<SLOTP> A"
empty = true
ext4 {
use-mke2fs = true
features = '^64bit,^huge_file'
label = "ROOTA"
}
size = <ROOT_SIZE>
}
..becomes
image rootA.ext4 {
exec-post = "/path/to/image/post-processing/hook A"
empty = true
ext4 {
use-mke2fs = true
features = '^64bit,^huge_file'
label = "ROOTA"
}
size = 2.0G
}
Looking at the code, genimage assumes the numerical portion of size will be a single unsigned long long and cannot cope with a decimal point. I imagine this will only be a problem above 1G where the granularity can only be expressed with a decimal point, which is the case when using numfmt with si (or iec or iec-i) output unit specifiers.
I initially thought it was a problem with a 'point zero' rather than a 'point one', but this not the case:
ERROR: Invalid size suffix '.1G' in '2.1G'
Is there scope to handle numbers formatted with a decimal point, or should numbers over 1G be specified in M (or K)?
Cheers, -- Matt
fyi, I can work around this by using the following to format the size, instead of numfmt --to=si:
numfmt --to=none --to-unit=1000 --format=%f --suffix=K
But if you have the exact byte counts, why even bother with numfmt and not just put in the actual integer byte count? I don't think genimage should start supporting floating point numbers, because it's ill-defined what something like 2.1X would even mean, regardless of what suffix X is used (2.1 cannot be represented exactly as a float, so what would 2.1G mean in bytes?).
What if you don't have the exact byte count, and what about alignment requirements of partitions, etc? To be able to have granular control over a 1G partition size, the size can only be specified in M (or smaller) units. It's fine supporting G, but the difference between 1G and 2G is huge so usage of such a unit is somewhat meaningless unless the size requires no fractional part.
so what would 2.1G mean in bytes
Fair point :) I've got no issue with genimage not supporting decimal places, but lack of that support means some additional number fiddling is required (which is not a big deal).
So what exactly do you have if not byte count? I don't know much about numfmt, but this really sounds like an x-y-problem. Why do you want to use numfmt in the first place? I think the number fiddling is just as easy to do in shell directly, and can still produce somewhat legible genimage config. Say you have some size_in_KiB and you want to round that up to nearest MiB; that's just sed -i -e "s|<ROOT_SIZE>|$(( (size_in_KiB + 1023)/1024 ))M|"
Also, I think you shouldn't use --to=si or --to-unit=1000, because genimage interprets the K,M,G suffixes as the IEC ones, i.e. powers of 1024. Maybe that's not a problem, your partitions will just be 2.5 or 5% bigger than you'd otherwise expect.
I have the byte count but I also need to allocate additional space based on an algorithm. Your rounding example would work fine (and yes you're right - I should use base 1024 not 1000 with numfmt), but that's not really relevant to what's being discussed. It's not an x-y problem. I'm simply stating that to achieve granular sizing above 1G, a smaller unit needs to be used. As you correctly pointed out, even if genimage did support fractional sizing above 1G, 2.1G (for example) does not yield a 'usable' byte count, ie being divisible by 8. We can close this.