diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 91d130495e205505dbdc03c7507b7d46bbfcdbdd..3ede3d5ebca142a97914a7fb596cbfcd2d649ff6 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1035,7 +1035,11 @@ virCgroupNewVcpu; virCgroupPathOfController; virCgroupRemove; virCgroupRemoveRecursively; +virCgroupSetBlkioDeviceReadBps; +virCgroupSetBlkioDeviceReadIops; virCgroupSetBlkioDeviceWeight; +virCgroupSetBlkioDeviceWriteBps; +virCgroupSetBlkioDeviceWriteIops; virCgroupSetBlkioWeight; virCgroupSetCpuCfsPeriod; virCgroupSetCpuCfsQuota; diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 310a4760e6a471089df9a78dde363b927df1e594..cc0d5e8d08bde72aea62e9aa2562010c2c224c7a 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -113,9 +113,30 @@ static int virLXCCgroupSetupBlkioTune(virDomainDefPtr def, if (def->blkio.ndevices) { for (i = 0; i < def->blkio.ndevices; i++) { virBlkioDevicePtr dev = &def->blkio.devices[i]; - if (!dev->weight) - continue; - if (virCgroupSetBlkioDeviceWeight(cgroup, dev->path, dev->weight) < 0) + + if (dev->weight && + (virCgroupSetBlkioDeviceWeight(cgroup, dev->path, + dev->weight) < 0)) + return -1; + + if (dev->riops && + (virCgroupSetBlkioDeviceReadIops(cgroup, dev->path, + dev->riops) < 0)) + return -1; + + if (dev->wiops && + (virCgroupSetBlkioDeviceWriteIops(cgroup, dev->path, + dev->wiops) < 0)) + return -1; + + if (dev->rbps && + (virCgroupSetBlkioDeviceReadBps(cgroup, dev->path, + dev->rbps) < 0)) + return -1; + + if (dev->wbps && + (virCgroupSetBlkioDeviceWriteBps(cgroup, dev->path, + dev->wbps) < 0)) return -1; } } diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index a18955e779060fb0a3783d7bd72665a928bb5a0a..1cc929c5ecae2392318d45953d679da59d2caf85 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -400,10 +400,29 @@ qemuSetupBlkioCgroup(virDomainObjPtr vm) if (vm->def->blkio.ndevices) { for (i = 0; i < vm->def->blkio.ndevices; i++) { virBlkioDevicePtr dev = &vm->def->blkio.devices[i]; - if (!dev->weight) - continue; - if (virCgroupSetBlkioDeviceWeight(priv->cgroup, dev->path, - dev->weight) < 0) + if (dev->weight && + (virCgroupSetBlkioDeviceWeight(priv->cgroup, dev->path, + dev->weight) < 0)) + return -1; + + if (dev->riops && + (virCgroupSetBlkioDeviceReadIops(priv->cgroup, dev->path, + dev->riops) < 0)) + return -1; + + if (dev->wiops && + (virCgroupSetBlkioDeviceWriteIops(priv->cgroup, dev->path, + dev->wiops) < 0)) + return -1; + + if (dev->rbps && + (virCgroupSetBlkioDeviceReadBps(priv->cgroup, dev->path, + dev->rbps) < 0)) + return -1; + + if (dev->wbps && + (virCgroupSetBlkioDeviceWriteBps(priv->cgroup, dev->path, + dev->wbps) < 0)) return -1; } } diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 43eb64920ec61046ed5eb30db453a441818214d0..a6d60c54b59c4b6f1b0825ed205234ba4afb8c9f 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -1824,12 +1824,189 @@ virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight) return ret; } +/** + * virCgroupSetBlkioDeviceReadIops: + * @group: The cgroup to change block io setting for + * @path: The path of device + * @riops: The new device read iops throttle, or 0 to clear + * + * Returns: 0 on success, -1 on error + */ +int +virCgroupSetBlkioDeviceReadIops(virCgroupPtr group, + const char *path, + unsigned int riops) +{ + char *str; + struct stat sb; + int ret; + + if (stat(path, &sb) < 0) { + virReportSystemError(errno, + _("Path '%s' is not accessible"), + path); + return -1; + } + + if (!S_ISBLK(sb.st_mode)) { + virReportSystemError(EINVAL, + _("Path '%s' must be a block device"), + path); + return -1; + } + + if (virAsprintf(&str, "%d:%d %u", major(sb.st_rdev), + minor(sb.st_rdev), riops) < 0) + return -1; + + ret = virCgroupSetValueStr(group, + VIR_CGROUP_CONTROLLER_BLKIO, + "blkio.throttle.read_iops_device", + str); + + VIR_FREE(str); + return ret; +} + /** - * virCgroupSetBlkioDeviceWeight: + * virCgroupSetBlkioDeviceWriteIops: + * @group: The cgroup to change block io setting for + * @path: The path of device + * @wiops: The new device write iops throttle, or 0 to clear + * + * Returns: 0 on success, -1 on error + */ +int +virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group, + const char *path, + unsigned int wiops) +{ + char *str; + struct stat sb; + int ret; + + if (stat(path, &sb) < 0) { + virReportSystemError(errno, + _("Path '%s' is not accessible"), + path); + return -1; + } + + if (!S_ISBLK(sb.st_mode)) { + virReportSystemError(EINVAL, + _("Path '%s' must be a block device"), + path); + return -1; + } + + if (virAsprintf(&str, "%d:%d %u", major(sb.st_rdev), + minor(sb.st_rdev), wiops) < 0) + return -1; + + ret = virCgroupSetValueStr(group, + VIR_CGROUP_CONTROLLER_BLKIO, + "blkio.throttle.write_iops_device", + str); + + VIR_FREE(str); + return ret; +} + + +/** + * virCgroupSetBlkioDeviceReadBps: + * @group: The cgroup to change block io setting for + * @path: The path of device + * @rbps: The new device read bps throttle, or 0 to clear + * + * Returns: 0 on success, -1 on error + */ +int +virCgroupSetBlkioDeviceReadBps(virCgroupPtr group, + const char *path, + unsigned long long rbps) +{ + char *str; + struct stat sb; + int ret; + + if (stat(path, &sb) < 0) { + virReportSystemError(errno, + _("Path '%s' is not accessible"), + path); + return -1; + } + + if (!S_ISBLK(sb.st_mode)) { + virReportSystemError(EINVAL, + _("Path '%s' must be a block device"), + path); + return -1; + } + + if (virAsprintf(&str, "%d:%d %llu", major(sb.st_rdev), + minor(sb.st_rdev), rbps) < 0) + return -1; + + ret = virCgroupSetValueStr(group, + VIR_CGROUP_CONTROLLER_BLKIO, + "blkio.throttle.read_bps_device", + str); + + VIR_FREE(str); + return ret; +} + +/** + * virCgroupSetBlkioDeviceWriteBps: + * @group: The cgroup to change block io setting for + * @path: The path of device + * @wbps: The new device write bps throttle, or 0 to clear * - * @group: The cgroup to change io device weight device for - * @path: The device with a weight to alter + * Returns: 0 on success, -1 on error + */ +int +virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group, + const char *path, + unsigned long long wbps) +{ + char *str; + struct stat sb; + int ret; + + if (stat(path, &sb) < 0) { + virReportSystemError(errno, + _("Path '%s' is not accessible"), + path); + return -1; + } + + if (!S_ISBLK(sb.st_mode)) { + virReportSystemError(EINVAL, + _("Path '%s' must be a block device"), + path); + return -1; + } + + if (virAsprintf(&str, "%d:%d %llu", major(sb.st_rdev), + minor(sb.st_rdev), wbps) < 0) + return -1; + + ret = virCgroupSetValueStr(group, + VIR_CGROUP_CONTROLLER_BLKIO, + "blkio.throttle.write_bps_device", + str); + + VIR_FREE(str); + return ret; +} + + +/** + * virCgroupSetBlkioDeviceWeight: + * @group: The cgroup to change block io setting for + * @path: The path of device * @weight: The new device weight (100-1000), * (10-1000) after kernel 2.6.39, or 0 to clear * @@ -1874,7 +2051,6 @@ virCgroupSetBlkioDeviceWeight(virCgroupPtr group, } - /** * virCgroupSetMemory: * @@ -3312,6 +3488,46 @@ virCgroupSetBlkioDeviceWeight(virCgroupPtr group ATTRIBUTE_UNUSED, return -1; } +int +virCgroupSetBlkioDeviceReadIops(virCgroupPtr group ATTRIBUTE_UNUSED, + const char *path ATTRIBUTE_UNUSED, + unsigned int riops ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Control groups not supported on this platform")); + return -1; +} + +int +virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group ATTRIBUTE_UNUSED, + const char *path ATTRIBUTE_UNUSED, + unsigned int wiops ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Control groups not supported on this platform")); + return -1; +} + +int +virCgroupSetBlkioDeviceReadBps(virCgroupPtr group ATTRIBUTE_UNUSED, + const char *path ATTRIBUTE_UNUSED, + unsigned long long rbps ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Control groups not supported on this platform")); + return -1; +} + +int +virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group ATTRIBUTE_UNUSED, + const char *path ATTRIBUTE_UNUSED, + unsigned long long wbps ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", + _("Control groups not supported on this platform")); + return -1; +} + int virCgroupSetMemory(virCgroupPtr group ATTRIBUTE_UNUSED, diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h index 835eb306896eacac5208a111fbc85ec99c112c5f..a70eb18aad41b65e699645d922b6cab9d1115f2b 100644 --- a/src/util/vircgroup.h +++ b/src/util/vircgroup.h @@ -126,6 +126,22 @@ int virCgroupSetBlkioDeviceWeight(virCgroupPtr group, const char *path, unsigned int weight); +int virCgroupSetBlkioDeviceReadIops(virCgroupPtr group, + const char *path, + unsigned int riops); + +int virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group, + const char *path, + unsigned int wiops); + +int virCgroupSetBlkioDeviceReadBps(virCgroupPtr group, + const char *path, + unsigned long long rbps); + +int virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group, + const char *path, + unsigned long long wbps); + int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb); int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml b/tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml index 743cf2958ff7f9499ff552c05f55884c110f2e46..bfb5b0378269347180c397f4041d44fc99f0ce57 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-blkiotune-device.xml @@ -8,10 +8,18 @@ /dev/sda 400 + 10000 + 10000 + 10000 + 10000 /dev/sdb 900 + 20000 + 20000 + 20000 + 20000 1