Re: [libvirt] [PATCH v2] domain: fix parsing of memory tunables on 32-bit machines

2014-10-31 Thread Martin Kletzander

On Thu, Oct 30, 2014 at 02:00:34PM -0600, Eric Blake wrote:

Commit 6c9a8a4 (Oct 2014) exposed a long-standing issue on 32-bit
machines: code related to virDomainSetMemoryParameters has always
been documented as using a 64-bit limit, but it was implemented by
calling virDomainParseMemory which enforced an 'unsigned long'
limit.  Since VIR_DOMAIN_MEMORY_PARAM_UNLIMITED capped to a
long is -1, but virDomainParseScaledValue no longer accepts
negative values, an attempt to use 2^53-1 as a hard memory limit
started failing the testsuite.  However, the problem with capping
things artificially low has existed for much longer - ever since
commits 4888f0fb and 2e22f23 (Mar 2012) switched internal tracking
from 'unsigned long' to 'unsigned long long' (prior to that time,
the cap was a side-effect of the choice of types).  We _have_ to
cap the balloon memory values, (no thanks to baked in 'unsigned long'
of API such as virDomainSetMaxMemory or virDomainGetInfo with no


Oh, this is why it needs to be capped.  That makes sense.  And great
to have it in the comment next to those variables!


counterpart API that guarantees 64-bit access to those numbers)
but memory parameters have never needed the artificial limit.

At any rate, the solution is to make the parser function gain a
parameter, and only do the reduced 32-bit cap for the values that
are constrained due to API.

* src/conf/domain_conf.h (_virDomainMemtune): Add comments.
* src/conf/domain_conf.c (virDomainParseMemory): Add parameter.
(virDomainDefParseXML): Adjust callers.

Signed-off-by: Eric Blake ebl...@redhat.com
---
src/conf/domain_conf.c | 25 ++---
src/conf/domain_conf.h | 14 --
2 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 39befb0..c594325 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -6373,19 +6373,22 @@ virDomainParseScaledValue(const char *xpath,


/* Parse a memory element located at XPATH within CTXT, and store the
- * result into MEM.  If REQUIRED, then the value must exist;
- * otherwise, the value is optional.  The value is in blocks of 1024.
- * Return 0 on success, -1 on failure after issuing error.  */
+ * result into MEM, in blocks of 1024.  If REQUIRED, then the value
+ * must exist; otherwise, the value is optional.  The value must not
+ * exceed VIR_DOMAIN_MEMORY_PARAM_UNLIMITED once scaled; additionally,
+ * if CAPPED is true, the value must fit within an unsigned long (only
+ * matters on 32-bit platforms).  Return 0 on success, -1 on failure
+ * after issuing error.  */


The last sentence (Return ...) could be in its own paragraph even
though our documentation is not created for these functions.

ACK with that and safe for freeze and also build-breaker for 32-bit
machines.

Martin


signature.asc
Description: Digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v2] domain: fix parsing of memory tunables on 32-bit machines

2014-10-31 Thread Eric Blake
On 10/31/2014 12:20 AM, Martin Kletzander wrote:
 On Thu, Oct 30, 2014 at 02:00:34PM -0600, Eric Blake wrote:
 Commit 6c9a8a4 (Oct 2014) exposed a long-standing issue on 32-bit
 machines: code related to virDomainSetMemoryParameters has always
 been documented as using a 64-bit limit, but it was implemented by
 calling virDomainParseMemory which enforced an 'unsigned long'
 limit.  Since VIR_DOMAIN_MEMORY_PARAM_UNLIMITED capped to a
 long is -1, but virDomainParseScaledValue no longer accepts
 negative values, an attempt to use 2^53-1 as a hard memory limit
 started failing the testsuite.  However, the problem with capping
 things artificially low has existed for much longer - ever since
 commits 4888f0fb and 2e22f23 (Mar 2012) switched internal tracking
 from 'unsigned long' to 'unsigned long long' (prior to that time,
 the cap was a side-effect of the choice of types).  We _have_ to
 cap the balloon memory values, (no thanks to baked in 'unsigned long'
 of API such as virDomainSetMaxMemory or virDomainGetInfo with no
 
 Oh, this is why it needs to be capped.  That makes sense.  And great
 to have it in the comment next to those variables!

Comments can make a world of difference :)

 + * exceed VIR_DOMAIN_MEMORY_PARAM_UNLIMITED once scaled; additionally,
 + * if CAPPED is true, the value must fit within an unsigned long (only
 + * matters on 32-bit platforms).  Return 0 on success, -1 on failure
 + * after issuing error.  */
 
 The last sentence (Return ...) could be in its own paragraph even
 though our documentation is not created for these functions.
 
 ACK with that and safe for freeze and also build-breaker for 32-bit
 machines.

Tweaked and pushed.

-- 
Eric Blake   eblake redhat com+1-919-301-3266
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v2] domain: fix parsing of memory tunables on 32-bit machines

2014-10-30 Thread Eric Blake
Commit 6c9a8a4 (Oct 2014) exposed a long-standing issue on 32-bit
machines: code related to virDomainSetMemoryParameters has always
been documented as using a 64-bit limit, but it was implemented by
calling virDomainParseMemory which enforced an 'unsigned long'
limit.  Since VIR_DOMAIN_MEMORY_PARAM_UNLIMITED capped to a
long is -1, but virDomainParseScaledValue no longer accepts
negative values, an attempt to use 2^53-1 as a hard memory limit
started failing the testsuite.  However, the problem with capping
things artificially low has existed for much longer - ever since
commits 4888f0fb and 2e22f23 (Mar 2012) switched internal tracking
from 'unsigned long' to 'unsigned long long' (prior to that time,
the cap was a side-effect of the choice of types).  We _have_ to
cap the balloon memory values, (no thanks to baked in 'unsigned long'
of API such as virDomainSetMaxMemory or virDomainGetInfo with no
counterpart API that guarantees 64-bit access to those numbers)
but memory parameters have never needed the artificial limit.

At any rate, the solution is to make the parser function gain a
parameter, and only do the reduced 32-bit cap for the values that
are constrained due to API.

* src/conf/domain_conf.h (_virDomainMemtune): Add comments.
* src/conf/domain_conf.c (virDomainParseMemory): Add parameter.
(virDomainDefParseXML): Adjust callers.

Signed-off-by: Eric Blake ebl...@redhat.com
---
 src/conf/domain_conf.c | 25 ++---
 src/conf/domain_conf.h | 14 --
 2 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 39befb0..c594325 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -6373,19 +6373,22 @@ virDomainParseScaledValue(const char *xpath,


 /* Parse a memory element located at XPATH within CTXT, and store the
- * result into MEM.  If REQUIRED, then the value must exist;
- * otherwise, the value is optional.  The value is in blocks of 1024.
- * Return 0 on success, -1 on failure after issuing error.  */
+ * result into MEM, in blocks of 1024.  If REQUIRED, then the value
+ * must exist; otherwise, the value is optional.  The value must not
+ * exceed VIR_DOMAIN_MEMORY_PARAM_UNLIMITED once scaled; additionally,
+ * if CAPPED is true, the value must fit within an unsigned long (only
+ * matters on 32-bit platforms).  Return 0 on success, -1 on failure
+ * after issuing error.  */
 static int
 virDomainParseMemory(const char *xpath, xmlXPathContextPtr ctxt,
- unsigned long long *mem, bool required)
+ unsigned long long *mem, bool required, bool capped)
 {
 int ret = -1;
 unsigned long long bytes, max;

 /* On 32-bit machines, our bound is 0x * KiB. On 64-bit
  * machines, our bound is off_t (2^63).  */
-if (sizeof(unsigned long)  sizeof(long long))
+if (capped  sizeof(unsigned long)  sizeof(long long))
 max = 1024ull * ULONG_MAX;
 else
 max = LLONG_MAX;
@@ -12215,11 +12218,11 @@ virDomainDefParseXML(xmlDocPtr xml,

 /* Extract domain memory */
 if (virDomainParseMemory(./memory[1], ctxt,
- def-mem.max_balloon, true)  0)
+ def-mem.max_balloon, true, true)  0)
 goto error;

 if (virDomainParseMemory(./currentMemory[1], ctxt,
- def-mem.cur_balloon, false)  0)
+ def-mem.cur_balloon, false, true)  0)
 goto error;

 /* and info about it */
@@ -12339,19 +12342,19 @@ virDomainDefParseXML(xmlDocPtr xml,

 /* Extract other memory tunables */
 if (virDomainParseMemory(./memtune/hard_limit[1], ctxt,
- def-mem.hard_limit, false)  0)
+ def-mem.hard_limit, false, false)  0)
 goto error;

 if (virDomainParseMemory(./memtune/soft_limit[1], ctxt,
- def-mem.soft_limit, false)  0)
+ def-mem.soft_limit, false, false)  0)
 goto error;

 if (virDomainParseMemory(./memtune/min_guarantee[1], ctxt,
- def-mem.min_guarantee, false)  0)
+ def-mem.min_guarantee, false, false)  0)
 goto error;

 if (virDomainParseMemory(./memtune/swap_hard_limit[1], ctxt,
- def-mem.swap_hard_limit, false)  0)
+ def-mem.swap_hard_limit, false, false)  0)
 goto error;

 n = virXPathULong(string(./vcpu[1]), ctxt, count);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9908d88..fbb3b2f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1966,8 +1966,10 @@ typedef struct _virDomainMemtune virDomainMemtune;
 typedef virDomainMemtune *virDomainMemtunePtr;

 struct _virDomainMemtune {
-unsigned long long max_balloon; /* in kibibytes */
-unsigned long long cur_balloon; /* in kibibytes */
+unsigned