On Wed, Apr 15, 2026 at 19:28:15 +0200, Roman Bogorodskiy wrote:
> FreeBSD supports resource limiting with the rctl(4) framework.
> It supports various resource types, including I/O resources.
> It allows to limit resources for users, processes, login classes,
> and jails.
> 
> To apply blkiotune limits set limits for the bhyve process.
> 
> I/O related resources supported by rctl(4) are:
> 
>   readbps            filesystem reads, in bytes per second
>   writebps           filesystem writes, in bytes per second
>   readiops           filesystem reads, in operations per second
>   writeiops          filesystem writes, in operations per second
> 
> Thus, the actual commands look like:
> 
> rctl -a process:$bhyvepid:writebps:throttle=10000000
> rctl -a process:$bhyvepid:readbps:throttle=10000000
> rctl -a process:$bhyvepid:writeiops:throttle=20000
> rctl -a process:$bhyvepid:readiops:throttle=20000
> 
> This is different from the current blkiotune modeling in libvirt as
> it requires specific device to apply limits to. To adapt this model
> to per-domain I/O limits, update domain schema to specify "*" as a
> device name.
> 
> The rctl(8) may be not available or not enabled, so add a capability
> check for that.
> 
> Per process rules get removed when the process disappears, so no special
> clean up is necessary.
> 
> Signed-off-by: Roman Bogorodskiy <[email protected]>
> ---
> Changes since v1:
> 
>  - Documented the "*" device name value in formatdomain.rst                   
>                                                                               
>                                                                               
>                                                                              
>  - Extended bhyve driver validation to allow only "*" devices                 
>                                                                               
>                                                                               
>                                                                              
>    and do no allow specifying device weight, added tests                      
>                                                                               
>                                                                               
>                                                                              
>    for these cases                                                            
>                                                                               
>                                                                               
>                                                                              
>  - Updated the RCTL macro to execute the rctl(8) command right                
>                                                                               
>                                                                               
>                                                                              
>    away instead of building an array of rules and looping                     
>                                                                               
>                                                                               
>                                                                              
>    through it once again                                                      
>                                                                               
>                                                                               
>                                                                              
>  - Minor formatting fixes
> 
>  docs/formatdomain.rst                         | 13 ++++--
>  src/bhyve/bhyve_capabilities.c                | 23 ++++++++++
>  src/bhyve/bhyve_capabilities.h                |  1 +
>  src/bhyve/bhyve_domain.c                      | 20 +++++++++
>  src/bhyve/bhyve_process.c                     | 45 +++++++++++++++++++
>  src/conf/schemas/domaincommon.rng             |  5 ++-
>  ...bhyvexml2argv-blkiotune-invalid-device.xml | 32 +++++++++++++
>  ...yvexml2argv-blkiotune-multiple-devices.xml | 39 ++++++++++++++++
>  .../x86_64/bhyvexml2argv-blkiotune-weight.xml | 33 ++++++++++++++
>  .../x86_64/bhyvexml2argv-blkiotune.args       | 10 +++++
>  .../x86_64/bhyvexml2argv-blkiotune.ldargs     |  4 ++
>  .../x86_64/bhyvexml2argv-blkiotune.xml        | 32 +++++++++++++
>  tests/bhyvexml2argvtest.c                     |  4 ++
>  .../x86_64/bhyvexml2xmlout-blkiotune.xml      | 42 +++++++++++++++++
>  tests/bhyvexml2xmltest.c                      |  4 ++
>  15 files changed, 302 insertions(+), 5 deletions(-)
>  create mode 100644 
> tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-blkiotune-invalid-device.xml
>  create mode 100644 
> tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-blkiotune-multiple-devices.xml
>  create mode 100644 
> tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-blkiotune-weight.xml
>  create mode 100644 
> tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-blkiotune.args
>  create mode 100644 
> tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-blkiotune.ldargs
>  create mode 100644 tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-blkiotune.xml
>  create mode 100644 
> tests/bhyvexml2xmloutdata/x86_64/bhyvexml2xmlout-blkiotune.xml
> 
> diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
> index 1a4bd4c6e9..6c4e067072 100644
> --- a/docs/formatdomain.rst
> +++ b/docs/formatdomain.rst
> @@ -1367,10 +1367,15 @@ Block I/O Tuning
>     associated with each guest disk device (contrast this to the <iotune>
>     element of a disk definition (See `Hard drives, floppy disks, CDROMs`_)
>     which can applies to an individual disk).  Each ``device`` element has
> -   two mandatory sub-elements, ``path`` describing the absolute path of the
> -   device, and ``weight`` giving the relative weight of that device, in the
> -   range [100, 1000]. After kernel 2.6.39, the value could be in the range 
> [10,
> -   1000]. :since:`Since 0.9.8`
> +   a mandatory  ``path`` sub-element describing the absolute path of the
> +   device.
> +
> +   A special value ``*`` can be used to throttle all domain
> +   devices. :since:`Since 12.3.0, bhyve`
> +
> +   An optional ``weight`` sub-element specifies the relative
> +   weight of the device, in the range [100, 1000]. After kernel 2.6.39,
> +   the value could be in the range [10, 1000]. :since:`Since 0.9.8`
>     Additionally, the following optional sub-elements can be used:
>  
>     ``read_bytes_sec``

[...]

> diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c
> index 4594d7673f..7bce6a4bc0 100644
> --- a/src/bhyve/bhyve_domain.c
> +++ b/src/bhyve/bhyve_domain.c
> @@ -464,6 +464,26 @@ bhyveDomainDefValidate(const virDomainDef *def,
>          }
>      }
>  
> +    if (def->blkio.ndevices > 1) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("Per device I/O tuning is not supported"));
> +        return -1;
> +    } else if (def->blkio.ndevices == 1) {
> +        virBlkioDevice *device = &def->blkio.devices[0];
> +
> +        if (STRNEQ(device->path, "*")) {
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                           _("Per device I/O tuning is not supported"));
> +            return -1;
> +        }
> +
> +        if (device->weight != 0) {
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                           _("Only \"*\" is supported as a device path for 
> I/O tuning"));

The message doesn't correspond with what the check rejects.

I'd go with something along:
  _("The 'weight' I/O tuning setting doesn't make sense with '*')

> +            return -1;
> +        }
> +    }
> +
>      if (!def->os.loader)
>          return 0;
>  
> diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c
> index 1d436da609..3eb807b9fe 100644
> --- a/src/bhyve/bhyve_process.c
> +++ b/src/bhyve/bhyve_process.c
> @@ -34,6 +34,7 @@
>  
>  #include "bhyve_device.h"
>  #include "bhyve_driver.h"
> +#include "bhyve_capabilities.h"
>  #include "bhyve_command.h"
>  #include "bhyve_firmware.h"
>  #include "bhyve_monitor.h"
> @@ -132,6 +133,47 @@ bhyveProcessStopHook(struct _bhyveConn *driver,
>                  VIR_HOOK_SUBOP_END, NULL, xml, NULL);
>  }
>  
> +static int
> +bhyveSetResourceLimits(struct _bhyveConn *driver, virDomainObj *vm)
> +{
> +    virBlkioDevice *device;
> +
> +    if (vm->def->blkio.ndevices != 1)
> +        return 0;
> +
> +    if ((bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_RCTL) == 0) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("Cannot set resource limits: RACCT/RCTL is either 
> not supported or not enabled"));
> +        return -1;
> +    }
> +
> +    device = &vm->def->blkio.devices[0];
> +
> +#define BHYVE_APPLY_RCTL_RULE(field, type, format) \
> +    do { \
> +        if ((field)) { \
> +            g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER; \
> +            g_autofree char *rule = NULL; \
> +            g_autoptr(virCommand) cmd = virCommandNew("rctl"); \
> +            virBufferAsprintf(&buf, "process:%d:" type ":throttle=" format, \
> +                              vm->pid, (field)); \
> +            rule = virBufferContentAndReset(&buf); \
> +            virCommandAddArgList(cmd, "-a", rule, NULL); \

You can simplify formatting of the command so that the extra virBuffer
and char* are not needed:
            g_autoptr(virCommand) cmd = virCommandNewList("rctl", "-a", NULL);
            virCommandAddArgFormat(cmd, "process:%d:" type ":throttle=" format,
                                   vm->pid, (field));

> +            if (virCommandRun(cmd, NULL) < 0) \
> +                return -1; \
> +         } \
> +    } while (0)
> +
> +    BHYVE_APPLY_RCTL_RULE(device->riops, "readiops", "%u");
> +    BHYVE_APPLY_RCTL_RULE(device->wiops, "writeiops", "%u");
> +    BHYVE_APPLY_RCTL_RULE(device->rbps, "readbps", "%llu");
> +    BHYVE_APPLY_RCTL_RULE(device->wbps, "writebps", "%llu");
> +
> +#undef BHYVE_APPLY_RCTL_RULE
> +
> +    return 0;
> +}
> +
>  static int
>  virBhyveProcessStartImpl(struct _bhyveConn *driver,
>                           virDomainObj *vm,

Reviewed-by: Peter Krempa <[email protected]>

Reply via email to