Red Hat Bugzilla – Bug 849748
vgs --units handling is not accurate
Last modified: 2012-08-21 12:26:57 EDT
Description of problem:
$ vgs --noheadings -o vg_free brawl
$ vgs --noheadings -o vg_free --units 100G brawl
$ vgs --noheadings -o vg_free --units 100g brawl
$ lvcreate -n brawl0 -L 100G brawl
Volume group "brawl" has insufficient free space (25598 extents): 25600 required.
Notice the 100G giving 1.07U while smaller g gives 1.00U. Capital G should match what the first command printed, or is this somehow reversed?
Also notice that it actually does not have 1.00U, 1U is more than 99.99G available, which causes the failure of the last command. I'd prefer more conservative approach here and round it down and not up.
Version-Release number of selected component (if applicable):
lvm2-2.02.88-9.el5, both RHEL5 and 6 seem to be affected.
Steps to Reproduce:
1. create VG sized as in description and additional info
2. repeat the commands as in description
* optimistic rounding causing unexpected results when the output is used
* g/G mismatch in commands output/input
* conservative rounding down (so it yields 0.99U in commands above)
* g/G match (second command must print 0.99U instead of 1.07U)
SCSI device sda: 104857600 512-byte hdwr sectors (53687 MB)
sda: Write Protect is off
sda: Mode Sense: 49 00 00 08
SCSI device sda: drive cache: write back
SCSI device sdb: 104857600 512-byte hdwr sectors (53687 MB)
sdb: Write Protect is off
sdb: Mode Sense: 49 00 00 08
SCSI device sdb: drive cache: write back
PV VG Fmt Attr PSize PFree
/dev/sda1 brawl lvm2 a-- 50.00G 50.00G
/dev/sdb1 brawl lvm2 a-- 50.00G 50.00G
It uses sprintf() rounding of floats for output, which I think is sensible.
If you need the exact size, use, for example --units s or b.
# Default value for --units argument
units = "h"
# Since version 2.02.54, the tools distinguish between powers of
# 1024 bytes (e.g. KiB, MiB, GiB) and powers of 1000 bytes (e.g.
# KB, MB, GB).
The only extension I'd still like to make one day is:
/* FIXME Make precision configurable */
I don't think it's worth making the rounding configurable, since if you're doing anything where it actually matters, you'd want to know the exact size, and if you're just using lvcreate as in your example, you should be using the %FREE syntax anyway rather than specifying the exact size.
Input has always used case-insensitive multiples of 1024 (not 1000) and I considered the major upheaval of trying to update this to offer both 1024 and 1000 a few years ago, but felt it would cause far more trouble than it's worth, whichever way we did it.
Thanks for the comment Alasdair.
sprintf() rounding is good until you actually want to use the result. It should be possible to do floor() on the argument before supplying it to sprintf(). I was not asking for this to be configurable, but always use conservative (i.e. floor) approach.
The output should probably print small "g" (as it seems to do in rhel6) also in rhel5.
These two fixes would make --units actually reliable and it's output usable. I know there are workarounds but if this feature is present, it should be doing it's job correctly.
Can you please implement these two fixes?
Sorry, I don't plan to change these things.
Always rounding down assumes you aren't going to use the data in a case where you need to round up: we would *have* to make this configurable (probably per-field). I repeat: you should not be using that output field as input to something else except where you know the units divide exactly (e.g. extent size) and your 'lvcreate' example is not something anybody should be using.
Output used to be inconsistent and we fixed it upstream and in RHEL6 to use S.I. units. I pasted the bit from lvm.conf that has a flag to let you switch between the two behaviours. (We can't change the default during the life of RHEL5, but you can toggle it yourself.)
In case you didn't understand, the command you should be using (as explained in the lvcreate man page) is:
lvcreate -n brawl0 -l100%FREE brawl