提交 2e148612 编写于 作者: E Eric Blake

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.
上级 26545784
...@@ -236,13 +236,22 @@ ...@@ -236,13 +236,22 @@
<br/> <br/>
By default this is specified in bytes, but an optional attribute By default this is specified in bytes, but an optional attribute
<code>unit</code> can be specified to adjust the passed value. <code>unit</code> can be specified to adjust the passed value.
Values can be: 'K' (kibibytes, 2<sup>10</sup> or 1024 bytes), Values can be: 'B' or 'bytes' for bytes, 'KB' (kilobytes,
'M' (mebibytes, 2<sup>20</sup> or 1,048,576 bytes), 'G' 10<sup>3</sup> or 1000 bytes), 'K' or 'KiB' (kibibytes,
(gibibytes, 2<sup>30</sup> or 1,073,741,824 bytes), 'T' 2<sup>10</sup> or 1024 bytes), 'MB' (megabytes, 10<sup>6</sup>
(tebibytes, 2<sup>40</sup> or 1,099,511,627,776 bytes), 'P' or 1,000,000 bytes), 'M' or 'MiB' (mebibytes, 2<sup>20</sup>
(pebibytes, 2<sup>50</sup> or 1,125,899,906,842,624 bytes), or or 1,048,576 bytes), 'GB' (gigabytes, 10<sup>9</sup> or
'E' (exbibytes, 2<sup>60</sup> or 1,152,921,504,606,846,976 1,000,000,000 bytes), 'G' or 'GiB' (gibibytes, 2<sup>30</sup>
bytes). <span class="since">Since 0.4.1</span></dd> or 1,073,741,824 bytes), 'TB' (terabytes, 10<sup>12</sup> or
1,000,000,000,000 bytes), 'T' or 'TiB' (tebibytes,
2<sup>40</sup> or 1,099,511,627,776 bytes), 'PB' (petabytes,
10<sup>15</sup> or 1,000,000,000,000,000 bytes), 'P' or 'PiB'
(pebibytes, 2<sup>50</sup> or 1,125,899,906,842,624 bytes),
'EB' (exabytes, 10<sup>18</sup> or 1,000,000,000,000,000,000
bytes), or 'E' or 'EiB' (exbibytes, 2<sup>60</sup> or
1,152,921,504,606,846,976 bytes). <span class="since">Since
0.4.1, multi-character <code>unit</code> since
0.9.11</span></dd>
<dt><code>capacity</code></dt> <dt><code>capacity</code></dt>
<dd>Providing the logical capacity for the volume. This value is <dd>Providing the logical capacity for the volume. This value is
in bytes by default, but a <code>unit</code> attribute can be in bytes by default, but a <code>unit</code> attribute can be
......
...@@ -140,7 +140,7 @@ ...@@ -140,7 +140,7 @@
<define name='unit'> <define name='unit'>
<data type='string'> <data type='string'>
<param name='pattern'>(bytes)|[kKmMgGtTpPeE]</param> <param name='pattern'>([bB]([yY][tT][eE][sS]?)?)|([kKmMgGtTpPeE]([iI]?[bB])?)</param>
</data> </data>
</define> </define>
<define name='scaledInteger'> <define name='scaledInteger'>
......
...@@ -944,64 +944,17 @@ virStoragePoolDefFormat(virStoragePoolDefPtr def) { ...@@ -944,64 +944,17 @@ virStoragePoolDefFormat(virStoragePoolDefPtr def) {
static int static int
virStorageSize(const char *unit, virStorageSize(const char *unit,
const char *val, const char *val,
unsigned long long *ret) { unsigned long long *ret)
unsigned long long mult; {
char *end; if (virStrToLong_ull(val, NULL, 10, ret) < 0) {
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) {
virStorageReportError(VIR_ERR_XML_ERROR, virStorageReportError(VIR_ERR_XML_ERROR,
"%s", _("malformed capacity element")); "%s", _("malformed capacity element"));
return -1; return -1;
} }
if (*ret > (ULLONG_MAX / mult)) { /* off_t is signed, so you cannot create a file larger than 2**63
virStorageReportError(VIR_ERR_XML_ERROR, * bytes in the first place. */
"%s", _("capacity element value too large")); if (virScaleInteger(ret, unit, 1, LLONG_MAX) < 0)
return -1; return -1;
}
*ret *= mult;
return 0; return 0;
} }
......
<volume> <volume>
<name>sparse.img</name> <name>sparse.img</name>
<source/> <source/>
<capacity>10000000000</capacity> <capacity unit='GB'>10</capacity>
<allocation>0</allocation> <allocation unit='MiB'>0</allocation>
<target> <target>
<path>/var/lib/libvirt/images/sparse.img</path> <path>/var/lib/libvirt/images/sparse.img</path>
<permissions> <permissions>
......
<volume> <volume>
<name>sparse.img</name> <name>sparse.img</name>
<source/> <source/>
<capacity unit="T">1</capacity> <capacity unit="TiB">1</capacity>
<allocation>0</allocation> <allocation unit="bytes">0</allocation>
<target> <target>
<path>/var/lib/libvirt/images/sparse.img</path> <path>/var/lib/libvirt/images/sparse.img</path>
<permissions> <permissions>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册