From 2e14861224f4af54fb5747152263c88a6c23fe3b Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 5 Mar 2012 14:06:33 -0700 Subject: [PATCH] storage: support more scaling suffixes Disk manufacturers are fond of quoting sizes in powers of 10, rather than powers of 2 (after all, 2.1 GB sounds larger than 2.0 GiB, even though the exact opposite is true). So, we might as well follow coreutils' lead in supporting three types of suffix: single letter ${u} (which we already had) and ${u}iB for the power of 2, and ${u}B for power of 10. Additionally, it is impossible to create a file with more than 2**63 bytes, since off_t is signed (if you have enough storage to even create one 8EiB file, I'm jealous). This now reports failure up front rather than down the road when the kernel finally refuses an impossible size. * docs/schemas/basictypes.rng (unit): Add suffixes. * src/conf/storage_conf.c (virStorageSize): Use new function. * docs/formatstorage.html.in: Document it. * tests/storagevolxml2xmlin/vol-file-backing.xml: Test it. * tests/storagevolxml2xmlin/vol-file.xml: Likewise. --- docs/formatstorage.html.in | 23 ++++--- docs/schemas/basictypes.rng | 2 +- src/conf/storage_conf.c | 61 +++---------------- .../storagevolxml2xmlin/vol-file-backing.xml | 4 +- tests/storagevolxml2xmlin/vol-file.xml | 4 +- 5 files changed, 28 insertions(+), 66 deletions(-) diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in index acb21faa81..d0e4319c50 100644 --- a/docs/formatstorage.html.in +++ b/docs/formatstorage.html.in @@ -236,13 +236,22 @@
By default this is specified in bytes, but an optional attribute unit can be specified to adjust the passed value. - Values can be: 'K' (kibibytes, 210 or 1024 bytes), - 'M' (mebibytes, 220 or 1,048,576 bytes), 'G' - (gibibytes, 230 or 1,073,741,824 bytes), 'T' - (tebibytes, 240 or 1,099,511,627,776 bytes), 'P' - (pebibytes, 250 or 1,125,899,906,842,624 bytes), or - 'E' (exbibytes, 260 or 1,152,921,504,606,846,976 - bytes). Since 0.4.1 + Values can be: 'B' or 'bytes' for bytes, 'KB' (kilobytes, + 103 or 1000 bytes), 'K' or 'KiB' (kibibytes, + 210 or 1024 bytes), 'MB' (megabytes, 106 + or 1,000,000 bytes), 'M' or 'MiB' (mebibytes, 220 + or 1,048,576 bytes), 'GB' (gigabytes, 109 or + 1,000,000,000 bytes), 'G' or 'GiB' (gibibytes, 230 + or 1,073,741,824 bytes), 'TB' (terabytes, 1012 or + 1,000,000,000,000 bytes), 'T' or 'TiB' (tebibytes, + 240 or 1,099,511,627,776 bytes), 'PB' (petabytes, + 1015 or 1,000,000,000,000,000 bytes), 'P' or 'PiB' + (pebibytes, 250 or 1,125,899,906,842,624 bytes), + 'EB' (exabytes, 1018 or 1,000,000,000,000,000,000 + bytes), or 'E' or 'EiB' (exbibytes, 260 or + 1,152,921,504,606,846,976 bytes). Since + 0.4.1, multi-character unit since + 0.9.11
capacity
Providing the logical capacity for the volume. This value is in bytes by default, but a unit attribute can be diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index a50349c602..cc0bc1286d 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -140,7 +140,7 @@ - (bytes)|[kKmMgGtTpPeE] + ([bB]([yY][tT][eE][sS]?)?)|([kKmMgGtTpPeE]([iI]?[bB])?) diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 07f3f5b6dc..bdf62184c4 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -944,64 +944,17 @@ virStoragePoolDefFormat(virStoragePoolDefPtr def) { static int virStorageSize(const char *unit, const char *val, - unsigned long long *ret) { - unsigned long long mult; - char *end; - - if (!unit) { - mult = 1; - } else { - switch (unit[0]) { - case 'k': - case 'K': - mult = 1024ull; - break; - - case 'm': - case 'M': - mult = 1024ull * 1024ull; - break; - - case 'g': - case 'G': - mult = 1024ull * 1024ull * 1024ull; - break; - - case 't': - case 'T': - mult = 1024ull * 1024ull * 1024ull * 1024ull; - break; - - case 'p': - case 'P': - mult = 1024ull * 1024ull * 1024ull * 1024ull * 1024ull; - break; - - case 'e': - case 'E': - mult = 1024ull * 1024ull * 1024ull * 1024ull * 1024ull * - 1024ull; - break; - - default: - virStorageReportError(VIR_ERR_XML_ERROR, - _("unknown size units '%s'"), unit); - return -1; - } - } - - if (virStrToLong_ull (val, &end, 10, ret) < 0) { + unsigned long long *ret) +{ + if (virStrToLong_ull(val, NULL, 10, ret) < 0) { virStorageReportError(VIR_ERR_XML_ERROR, "%s", _("malformed capacity element")); return -1; } - if (*ret > (ULLONG_MAX / mult)) { - virStorageReportError(VIR_ERR_XML_ERROR, - "%s", _("capacity element value too large")); - return -1; - } - - *ret *= mult; + /* off_t is signed, so you cannot create a file larger than 2**63 + * bytes in the first place. */ + if (virScaleInteger(ret, unit, 1, LLONG_MAX) < 0) + return -1; return 0; } diff --git a/tests/storagevolxml2xmlin/vol-file-backing.xml b/tests/storagevolxml2xmlin/vol-file-backing.xml index c1a5837c6a..d23349e658 100644 --- a/tests/storagevolxml2xmlin/vol-file-backing.xml +++ b/tests/storagevolxml2xmlin/vol-file-backing.xml @@ -1,8 +1,8 @@ sparse.img - 10000000000 - 0 + 10 + 0 /var/lib/libvirt/images/sparse.img diff --git a/tests/storagevolxml2xmlin/vol-file.xml b/tests/storagevolxml2xmlin/vol-file.xml index d7de0aa23c..fdca510101 100644 --- a/tests/storagevolxml2xmlin/vol-file.xml +++ b/tests/storagevolxml2xmlin/vol-file.xml @@ -1,8 +1,8 @@ sparse.img - 1 - 0 + 1 + 0 /var/lib/libvirt/images/sparse.img