[libvirt] [PATCH 4/5] Add support for blkio tuning of LXC containers

Daniel Veillard veillard at redhat.com
Thu Nov 24 14:08:19 UTC 2011


On Thu, Nov 24, 2011 at 11:38:15AM +0000, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
> 
> * src/lxc/lxc_controller.c: Refactor setting of initial blkio
>   tuning parameters
> * src/lxc/lxc_driver.c: Enable live change of blkio tuning
> ---
>  src/lxc/lxc_controller.c |   31 ++++--
>  src/lxc/lxc_driver.c     |  283 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 305 insertions(+), 9 deletions(-)
> 
> diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
> index 1685e15..c17b172 100644
> --- a/src/lxc/lxc_controller.c
> +++ b/src/lxc/lxc_controller.c
> @@ -418,6 +418,26 @@ cleanup:
>  }
>  
>  
> +static int lxcSetContainerBlkioTune(virCgroupPtr cgroup, virDomainDefPtr def)
> +{
> +    int ret = -1;
> +
> +    if (def->blkio.weight) {
> +        int rc = virCgroupSetBlkioWeight(cgroup, def->blkio.weight);
> +        if (rc != 0) {
> +            virReportSystemError(-rc,
> +                                 _("Unable to set Blkio weight for domain %s"),
> +                                 def->name);
> +            goto cleanup;
> +        }
> +    }
> +
> +    ret = 0;
> +cleanup:
> +    return ret;
> +}
> +
> +
>  /**
>   * lxcSetContainerResources
>   * @def: pointer to virtual machine structure
> @@ -471,15 +491,8 @@ static int lxcSetContainerResources(virDomainDefPtr def)
>      if (lxcSetContainerCpuTune(cgroup, def) < 0)
>          goto cleanup;
>  
> -    if (def->blkio.weight) {
> -        rc = virCgroupSetBlkioWeight(cgroup, def->blkio.weight);
> -        if (rc != 0) {
> -            virReportSystemError(-rc,
> -                                 _("Unable to set Blkio weight for domain %s"),
> -                                 def->name);
> -            goto cleanup;
> -        }
> -    }
> +    if (lxcSetContainerBlkioTune(cgroup, def) < 0)
> +        goto cleanup;
>  
>      rc = virCgroupSetMemory(cgroup, def->mem.max_balloon);
>      if (rc != 0) {
> diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
> index 4445b5c..5099517 100644
> --- a/src/lxc/lxc_driver.c
> +++ b/src/lxc/lxc_driver.c
> @@ -3105,6 +3105,287 @@ lxcGetSchedulerParameters(virDomainPtr domain,
>      return lxcGetSchedulerParametersFlags(domain, params, nparams, 0);
>  }
>  
> +
> +static int lxcDomainSetBlkioParameters(virDomainPtr dom,
> +                                       virTypedParameterPtr params,
> +                                       int nparams,
> +                                       unsigned int flags)
> +{
> +    lxc_driver_t *driver = dom->conn->privateData;
> +    int i;
> +    virCgroupPtr group = NULL;
> +    virDomainObjPtr vm = NULL;
> +    virDomainDefPtr persistentDef = NULL;
> +    int ret = -1;
> +    bool isActive;
> +
> +    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
> +                  VIR_DOMAIN_AFFECT_CONFIG, -1);
> +    lxcDriverLock(driver);
> +
> +    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
> +
> +    if (vm == NULL) {
> +        lxcError(VIR_ERR_INTERNAL_ERROR,
> +                        _("No such domain %s"), dom->uuid);
> +        goto cleanup;
> +    }
> +
> +    isActive = virDomainObjIsActive(vm);
> +
> +    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
> +        if (isActive)
> +            flags = VIR_DOMAIN_AFFECT_LIVE;
> +        else
> +            flags = VIR_DOMAIN_AFFECT_CONFIG;
> +    }
> +
> +    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
> +        if (!isActive) {
> +            lxcError(VIR_ERR_OPERATION_INVALID,
> +                     "%s", _("domain is not running"));
> +            goto cleanup;
> +        }
> +
> +        if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
> +            lxcError(VIR_ERR_OPERATION_INVALID, _("blkio cgroup isn't mounted"));
> +            goto cleanup;
> +        }
> +
> +        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
> +            lxcError(VIR_ERR_INTERNAL_ERROR,
> +                     _("cannot find cgroup for domain %s"), vm->def->name);
> +            goto cleanup;
> +        }
> +    }
> +
> +    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
> +        if (!vm->persistent) {
> +            lxcError(VIR_ERR_OPERATION_INVALID, "%s",
> +                     _("cannot change persistent config of a transient domain"));
> +            goto cleanup;
> +        }
> +        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
> +            goto cleanup;
> +    }
> +
> +    ret = 0;
> +    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
> +        for (i = 0; i < nparams; i++) {
> +            virTypedParameterPtr param = &params[i];
> +
> +            if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
> +                int rc;
> +                if (param->type != VIR_TYPED_PARAM_UINT) {
> +                    lxcError(VIR_ERR_INVALID_ARG, "%s",
> +                             _("invalid type for blkio weight tunable, expected a 'unsigned int'"));
> +                    ret = -1;
> +                    continue;
> +                }
> +
> +                if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
> +                    lxcError(VIR_ERR_INVALID_ARG, "%s",
> +                             _("out of blkio weight range."));
> +                    ret = -1;
> +                    continue;
> +                }
> +
> +                rc = virCgroupSetBlkioWeight(group, params[i].value.ui);
> +                if (rc != 0) {
> +                    virReportSystemError(-rc, "%s",
> +                                         _("unable to set blkio weight tunable"));
> +                    ret = -1;
> +                }
> +            } else {
> +                lxcError(VIR_ERR_INVALID_ARG,
> +                         _("Parameter `%s' not supported"), param->field);
> +                ret = -1;
> +            }
> +        }
> +    } else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
> +        /* Clang can't see that if we get here, persistentDef was set.  */
> +        sa_assert(persistentDef);
> +
> +        for (i = 0; i < nparams; i++) {
> +            virTypedParameterPtr param = &params[i];
> +
> +            if (STREQ(param->field, VIR_DOMAIN_BLKIO_WEIGHT)) {
> +                if (param->type != VIR_TYPED_PARAM_UINT) {
> +                    lxcError(VIR_ERR_INVALID_ARG, "%s",
> +                             _("invalid type for blkio weight tunable, expected a 'unsigned int'"));
> +                    ret = -1;
> +                    continue;
> +                }
> +
> +                if (params[i].value.ui > 1000 || params[i].value.ui < 100) {
> +                    lxcError(VIR_ERR_INVALID_ARG, "%s",
> +                             _("out of blkio weight range."));
> +                    ret = -1;
> +                    continue;
> +                }
> +
> +                persistentDef->blkio.weight = params[i].value.ui;
> +            } else {
> +                lxcError(VIR_ERR_INVALID_ARG,
> +                         _("Parameter `%s' not supported"), param->field);
> +                ret = -1;
> +            }
> +        }
> +
> +        if (virDomainSaveConfig(driver->configDir, persistentDef) < 0)
> +            ret = -1;
> +    }
> +
> +cleanup:
> +    virCgroupFree(&group);
> +    if (vm)
> +        virDomainObjUnlock(vm);
> +    lxcDriverUnlock(driver);
> +    return ret;
> +}
> +
> +
> +#define LXC_NB_BLKIO_PARAM  1
> +static int lxcDomainGetBlkioParameters(virDomainPtr dom,
> +                                       virTypedParameterPtr params,
> +                                       int *nparams,
> +                                       unsigned int flags)
> +{
> +    lxc_driver_t *driver = dom->conn->privateData;
> +    int i;
> +    virCgroupPtr group = NULL;
> +    virDomainObjPtr vm = NULL;
> +    virDomainDefPtr persistentDef = NULL;
> +    unsigned int val;
> +    int ret = -1;
> +    int rc;
> +    bool isActive;
> +
> +    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
> +                  VIR_DOMAIN_AFFECT_CONFIG, -1);
> +    lxcDriverLock(driver);
> +
> +    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
> +
> +    if (vm == NULL) {
> +        lxcError(VIR_ERR_INTERNAL_ERROR,
> +                 _("No such domain %s"), dom->uuid);
> +        goto cleanup;
> +    }
> +
> +    if ((*nparams) == 0) {
> +        /* Current number of blkio parameters supported by cgroups */
> +        *nparams = LXC_NB_BLKIO_PARAM;
> +        ret = 0;
> +        goto cleanup;
> +    }
> +
> +    isActive = virDomainObjIsActive(vm);
> +
> +    if (flags == VIR_DOMAIN_AFFECT_CURRENT) {
> +        if (isActive)
> +            flags = VIR_DOMAIN_AFFECT_LIVE;
> +        else
> +            flags = VIR_DOMAIN_AFFECT_CONFIG;
> +    }
> +
> +    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
> +        if (!isActive) {
> +            lxcError(VIR_ERR_OPERATION_INVALID,
> +                     "%s", _("domain is not running"));
> +            goto cleanup;
> +        }
> +
> +        if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_BLKIO)) {
> +            lxcError(VIR_ERR_OPERATION_INVALID, _("blkio cgroup isn't mounted"));
> +            goto cleanup;
> +        }
> +
> +        if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) {
> +            lxcError(VIR_ERR_INTERNAL_ERROR,
> +                     _("cannot find cgroup for domain %s"), vm->def->name);
> +            goto cleanup;
> +        }
> +    }
> +
> +    if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
> +        if (!vm->persistent) {
> +            lxcError(VIR_ERR_OPERATION_INVALID, "%s",
> +                     _("cannot change persistent config of a transient domain"));
> +            goto cleanup;
> +        }
> +        if (!(persistentDef = virDomainObjGetPersistentDef(driver->caps, vm)))
> +            goto cleanup;
> +    }
> +
> +    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
> +        for (i = 0; i < *nparams && i < LXC_NB_BLKIO_PARAM; i++) {
> +            virTypedParameterPtr param = &params[i];
> +            val = 0;
> +            param->value.ui = 0;
> +            param->type = VIR_TYPED_PARAM_UINT;
> +
> +            switch (i) {
> +            case 0: /* fill blkio weight here */
> +                rc = virCgroupGetBlkioWeight(group, &val);
> +                if (rc != 0) {
> +                    virReportSystemError(-rc, "%s",
> +                                         _("unable to get blkio weight"));
> +                    goto cleanup;
> +                }
> +                if (virStrcpyStatic(param->field, VIR_DOMAIN_BLKIO_WEIGHT) == NULL) {
> +                    lxcError(VIR_ERR_INTERNAL_ERROR,
> +                             _("Field name '%s' too long"),
> +                             VIR_DOMAIN_BLKIO_WEIGHT);
> +                    goto cleanup;
> +                }
> +                param->value.ui = val;
> +                break;
> +
> +            default:
> +                break;
> +                /* should not hit here */
> +            }
> +        }
> +    } else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
> +        for (i = 0; i < *nparams && i < LXC_NB_BLKIO_PARAM; i++) {
> +            virTypedParameterPtr param = &params[i];
> +            val = 0;
> +            param->value.ui = 0;
> +            param->type = VIR_TYPED_PARAM_UINT;
> +
> +            switch (i) {
> +            case 0: /* fill blkio weight here */
> +                if (virStrcpyStatic(param->field, VIR_DOMAIN_BLKIO_WEIGHT) == NULL) {
> +                    lxcError(VIR_ERR_INTERNAL_ERROR,
> +                             _("Field name '%s' too long"),
> +                             VIR_DOMAIN_BLKIO_WEIGHT);
> +                    goto cleanup;
> +                }
> +                param->value.ui = persistentDef->blkio.weight;
> +                break;
> +
> +            default:
> +                break;
> +                /* should not hit here */
> +            }
> +        }
> +    }
> +
> +    if (LXC_NB_BLKIO_PARAM < *nparams)
> +        *nparams = LXC_NB_BLKIO_PARAM;
> +    ret = 0;
> +
> +cleanup:
> +    if (group)
> +        virCgroupFree(&group);
> +    if (vm)
> +        virDomainObjUnlock(vm);
> +    lxcDriverUnlock(driver);
> +    return ret;
> +}
> +
> +
>  #ifdef __linux__
>  static int
>  lxcDomainInterfaceStats(virDomainPtr dom,
> @@ -3600,6 +3881,8 @@ static virDriver lxcDriver = {
>      .domainSetMemory = lxcDomainSetMemory, /* 0.7.2 */
>      .domainSetMemoryParameters = lxcDomainSetMemoryParameters, /* 0.8.5 */
>      .domainGetMemoryParameters = lxcDomainGetMemoryParameters, /* 0.8.5 */
> +    .domainSetBlkioParameters = lxcDomainSetBlkioParameters, /* 0.9.8 */
> +    .domainGetBlkioParameters = lxcDomainGetBlkioParameters, /* 0.9.8 */
>      .domainGetInfo = lxcDomainGetInfo, /* 0.4.2 */
>      .domainGetState = lxcDomainGetState, /* 0.9.2 */
>      .domainGetXMLDesc = lxcDomainGetXMLDesc, /* 0.4.2 */

  ACK,

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list