[libvirt] [PATCH 1/3] cgroups: Redefine what "unlimited" means wrt memory limits

Daniel P. Berrange berrange at redhat.com
Thu Dec 12 12:02:29 UTC 2013


On Mon, Dec 09, 2013 at 09:22:51AM +0100, Martin Kletzander wrote:
> Since kernel 3.12 (commit 34ff8dc08956098563989d8599840b130be81252 in
> linux-stable.git in particular) the value for 'unlimited' in cgroup
> memory limits changed from LLONG_MAX to ULLONG_MAX.  Due to rather
> unfortunate choice of our VIR_DOMAIN_MEMORY_PARAM_UNLIMITED constant
> (which we transfer as an unsigned long long in Kibibytes), we ended up
> with the situation described below (applies to x86_64):
> 
>  - 2^64-1 (ULLONG_MAX) -- "unlimited" in kernel = 3.12
> 
>  - 2^63-1 (LLONG_MAX) -- "unlimited" in kernel < 3.12
>  - 2^63-1024 -- our PARAM_UNLIMITED scaled to Bytes
> 
>  - 2^53-1 -- our PARAM_UNLIMITED unscaled (in Kibibytes)
> 
> This means that when any number within (2^63-1, 2^64-1] is read from
> memory cgroup, we are transferring that number instead of "unlimited".
> Unfortunately, changing VIR_DOMAIN_MEMORY_PARAM_UNLIMITED would break
> ABI compatibility and thus we have to resort to a different solution.
> 
> With this patch every value greater than PARAM_UNLIMITED means
> "unlimited".  Even though this may seem misleading, we are already in
> such unclear situation when running 3.12 kernel with memory limits set
> to 2^63.
> 
> One example showing most of the problems at once (with kernel 3.12.2):
>  # virsh memtune asdf --hard-limit 9007199254740991 --swap-hard-limit -1
>  # echo 12345678901234567890 >\
> /sys/fs/cgroup/memory/machine/asdf.libvirt-qemu/memory.soft_limit_in_bytes
>  # virsh memtune asdf
>  hard_limit     : 18014398509481983
>  soft_limit     : 12056327051986884
>  swap_hard_limit: 18014398509481983
> 
> Signed-off-by: Martin Kletzander <mkletzan at redhat.com>
> ---
>  src/util/vircgroup.c | 57 +++++++++++++++++++++++++++++++++++-----------------
>  1 file changed, 39 insertions(+), 18 deletions(-)
> 
> diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
> index 9674328..43eb649 100644
> --- a/src/util/vircgroup.c
> +++ b/src/util/vircgroup.c
> @@ -1957,12 +1957,19 @@ int
>  virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb)
>  {
>      long long unsigned int limit_in_bytes;
> -    int ret;
> -    ret = virCgroupGetValueU64(group,
> -                               VIR_CGROUP_CONTROLLER_MEMORY,
> -                               "memory.limit_in_bytes", &limit_in_bytes);
> -    if (ret == 0)
> -        *kb = limit_in_bytes >> 10;
> +    int ret = -1;
> +
> +    if (virCgroupGetValueU64(group,
> +                             VIR_CGROUP_CONTROLLER_MEMORY,
> +                             "memory.limit_in_bytes", &limit_in_bytes) < 0)
> +        goto cleanup;
> +
> +    *kb = limit_in_bytes >> 10;
> +    if (*kb > VIR_DOMAIN_MEMORY_PARAM_UNLIMITED)
> +        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
> +
> +    ret = 0;
> + cleanup:
>      return ret;
>  }
> 
> @@ -2012,12 +2019,19 @@ int
>  virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb)
>  {
>      long long unsigned int limit_in_bytes;
> -    int ret;
> -    ret = virCgroupGetValueU64(group,
> -                               VIR_CGROUP_CONTROLLER_MEMORY,
> -                               "memory.soft_limit_in_bytes", &limit_in_bytes);
> -    if (ret == 0)
> -        *kb = limit_in_bytes >> 10;
> +    int ret = -1;
> +
> +    if (virCgroupGetValueU64(group,
> +                             VIR_CGROUP_CONTROLLER_MEMORY,
> +                             "memory.soft_limit_in_bytes", &limit_in_bytes) < 0)
> +        goto cleanup;
> +
> +    *kb = limit_in_bytes >> 10;
> +    if (*kb > VIR_DOMAIN_MEMORY_PARAM_UNLIMITED)
> +        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
> +
> +    ret = 0;
> + cleanup:
>      return ret;
>  }
> 
> @@ -2067,12 +2081,19 @@ int
>  virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb)
>  {
>      long long unsigned int limit_in_bytes;
> -    int ret;
> -    ret = virCgroupGetValueU64(group,
> -                               VIR_CGROUP_CONTROLLER_MEMORY,
> -                               "memory.memsw.limit_in_bytes", &limit_in_bytes);
> -    if (ret == 0)
> -        *kb = limit_in_bytes >> 10;
> +    int ret = -1;
> +
> +    if (virCgroupGetValueU64(group,
> +                             VIR_CGROUP_CONTROLLER_MEMORY,
> +                             "memory.memsw.limit_in_bytes", &limit_in_bytes) < 0)
> +        goto cleanup;
> +
> +    *kb = limit_in_bytes >> 10;
> +    if (*kb > VIR_DOMAIN_MEMORY_PARAM_UNLIMITED)
> +        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
> +
> +    ret = 0;
> + cleanup:
>      return ret;
>  }

ACK

Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list