Add support of the memtune's hard_limit configuration:

  <memtune>
    <hard_limit ... >
  </memtune>

to the bhyve driver.

Just like in the block I/O tuning case, memory limits are set using the
rctl(8) tool.

Syntax for that is:

 rctl -a process:<pid>:memoryuse:deny=1073741824

Extend bhyveSetResourceLimits() to execute this command if it's
requested by the domain XML.

Signed-off-by: Roman Bogorodskiy <[email protected]>
---
 src/bhyve/bhyve_domain.c                      |  8 ++++++
 src/bhyve/bhyve_process.c                     | 26 +++++++++++------
 ...vexml2argv-memtune-unsupported-params.args | 10 +++++++
 ...xml2argv-memtune-unsupported-params.ldargs |  4 +++
 ...yvexml2argv-memtune-unsupported-params.xml | 28 +++++++++++++++++++
 .../x86_64/bhyvexml2argv-memtune.args         | 10 +++++++
 .../x86_64/bhyvexml2argv-memtune.ldargs       |  4 +++
 .../x86_64/bhyvexml2argv-memtune.xml          | 26 +++++++++++++++++
 tests/bhyvexml2argvtest.c                     |  2 ++
 9 files changed, 109 insertions(+), 9 deletions(-)
 create mode 100644 
tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.args
 create mode 100644 
tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.ldargs
 create mode 100644 
tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.xml
 create mode 100644 tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.args
 create mode 100644 tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.ldargs
 create mode 100644 tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.xml

diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c
index 6367985efc..86e4de1fd8 100644
--- a/src/bhyve/bhyve_domain.c
+++ b/src/bhyve/bhyve_domain.c
@@ -541,6 +541,14 @@ bhyveDomainDefValidate(const virDomainDef *def,
         }
     }
 
+    if (virMemoryLimitIsSet(def->mem.soft_limit) ||
+        virMemoryLimitIsSet(def->mem.swap_hard_limit) ||
+        def->mem.min_guarantee) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Only 'hard_limit' memory tuning parameter is 
supported by bhyve"));
+            return -1;
+    }
+
     if (!def->os.loader)
         return 0;
 
diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c
index 7652a998e5..7baefeb63b 100644
--- a/src/bhyve/bhyve_process.c
+++ b/src/bhyve/bhyve_process.c
@@ -53,6 +53,7 @@
 #include "virnetdevbridge.h"
 #include "virnetdevtap.h"
 #include "virtime.h"
+#include "virutil.h"
 
 #define VIR_FROM_THIS   VIR_FROM_BHYVE
 
@@ -138,7 +139,8 @@ bhyveSetResourceLimits(struct _bhyveConn *driver, 
virDomainObj *vm)
 {
     virBlkioDevice *device;
 
-    if (vm->def->blkio.ndevices != 1)
+    if ((vm->def->blkio.ndevices != 1) &&
+        !virMemoryLimitIsSet(vm->def->mem.hard_limit))
         return 0;
 
     if ((bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_RCTL) == 0) {
@@ -147,24 +149,30 @@ bhyveSetResourceLimits(struct _bhyveConn *driver, 
virDomainObj *vm)
         return -1;
     }
 
-    device = &vm->def->blkio.devices[0];
-
-#define BHYVE_APPLY_RCTL_RULE(field, type, format) \
+#define BHYVE_APPLY_RCTL_RULE(field, type, action, format) \
     do { \
         if ((field)) { \
             g_autofree char *rule = NULL; \
             g_autoptr(virCommand) cmd = virCommandNewArgList("rctl", "-a", 
NULL); \
-            virCommandAddArgFormat(cmd, "process:%d:" type ":throttle=" 
format, \
+            virCommandAddArgFormat(cmd, "process:%d:" type ":" action "=" 
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");
+    if (vm->def->blkio.ndevices == 1) {
+        device = &vm->def->blkio.devices[0];
+
+        BHYVE_APPLY_RCTL_RULE(device->riops, "readiops", "throttle", "%u");
+        BHYVE_APPLY_RCTL_RULE(device->wiops, "writeiops", "throttle", "%u");
+        BHYVE_APPLY_RCTL_RULE(device->rbps, "readbps", "throttle", "%llu");
+        BHYVE_APPLY_RCTL_RULE(device->wbps, "writebps", "throttle", "%llu");
+    }
+
+    /* rctl(8) uses bytes for these values and def->mem.* uses kibibytes */
+    if (virMemoryLimitIsSet(vm->def->mem.hard_limit))
+        BHYVE_APPLY_RCTL_RULE(vm->def->mem.hard_limit * 1024, "memoryuse", 
"deny", "%llu");
 
 #undef BHYVE_APPLY_RCTL_RULE
 
diff --git 
a/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.args 
b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.args
new file mode 100644
index 0000000000..507e0be668
--- /dev/null
+++ 
b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.args
@@ -0,0 +1,10 @@
+bhyve \
+-c 1 \
+-m 214 \
+-u \
+-H \
+-P \
+-s 0:0,hostbridge \
+-s 2:0,ahci,hd:/tmp/freebsd.img \
+-s 3:0,virtio-net,faketapdev,mac=52:54:00:b9:94:02 \
+bhyve
diff --git 
a/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.ldargs
 
b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.ldargs
new file mode 100644
index 0000000000..5905f4b3e6
--- /dev/null
+++ 
b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.ldargs
@@ -0,0 +1,4 @@
+bhyveload \
+-m 214 \
+-d /tmp/freebsd.img \
+bhyve
diff --git 
a/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.xml 
b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.xml
new file mode 100644
index 0000000000..af1e25805d
--- /dev/null
+++ 
b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune-unsupported-params.xml
@@ -0,0 +1,28 @@
+<domain type='bhyve'>
+  <name>bhyve</name>
+  <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
+  <memory>219136</memory>
+  <memtune>
+    <soft_limit unit='M'>512</soft_limit>
+    <swap_hard_limit unit='G'>1</swap_hard_limit>
+    <min_guarantee unit='M'>128</min_guarantee>
+  </memtune>
+  <vcpu>1</vcpu>
+  <os>
+    <type>hvm</type>
+  </os>
+  <devices>
+    <disk type='file'>
+      <driver name='file' type='raw'/>
+      <source file='/tmp/freebsd.img'/>
+      <target dev='hda' bus='sata'/>
+      <address type='drive' controller='0' bus='0' target='2' unit='0'/>
+    </disk>
+    <interface type='bridge'>
+      <mac address='52:54:00:b9:94:02'/>
+      <model type='virtio'/>
+      <source bridge="virbr0"/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' 
function='0x0'/>
+    </interface>
+  </devices>
+</domain>
diff --git a/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.args 
b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.args
new file mode 100644
index 0000000000..507e0be668
--- /dev/null
+++ b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.args
@@ -0,0 +1,10 @@
+bhyve \
+-c 1 \
+-m 214 \
+-u \
+-H \
+-P \
+-s 0:0,hostbridge \
+-s 2:0,ahci,hd:/tmp/freebsd.img \
+-s 3:0,virtio-net,faketapdev,mac=52:54:00:b9:94:02 \
+bhyve
diff --git a/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.ldargs 
b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.ldargs
new file mode 100644
index 0000000000..5905f4b3e6
--- /dev/null
+++ b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.ldargs
@@ -0,0 +1,4 @@
+bhyveload \
+-m 214 \
+-d /tmp/freebsd.img \
+bhyve
diff --git a/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.xml 
b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.xml
new file mode 100644
index 0000000000..f8bcd23296
--- /dev/null
+++ b/tests/bhyvexml2argvdata/x86_64/bhyvexml2argv-memtune.xml
@@ -0,0 +1,26 @@
+<domain type='bhyve'>
+  <name>bhyve</name>
+  <uuid>df3be7e7-a104-11e3-aeb0-50e5492bd3dc</uuid>
+  <memory>219136</memory>
+  <memtune>
+    <hard_limit unit='M'>512</hard_limit>
+  </memtune>
+  <vcpu>1</vcpu>
+  <os>
+    <type>hvm</type>
+  </os>
+  <devices>
+    <disk type='file'>
+      <driver name='file' type='raw'/>
+      <source file='/tmp/freebsd.img'/>
+      <target dev='hda' bus='sata'/>
+      <address type='drive' controller='0' bus='0' target='2' unit='0'/>
+    </disk>
+    <interface type='bridge'>
+      <mac address='52:54:00:b9:94:02'/>
+      <model type='virtio'/>
+      <source bridge="virbr0"/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' 
function='0x0'/>
+    </interface>
+  </devices>
+</domain>
diff --git a/tests/bhyvexml2argvtest.c b/tests/bhyvexml2argvtest.c
index eb2c1d33b8..818b51e178 100644
--- a/tests/bhyvexml2argvtest.c
+++ b/tests/bhyvexml2argvtest.c
@@ -301,6 +301,8 @@ mymain(void)
     DO_TEST_FAILURE("virtio-console-too-many-ports");
     DO_TEST_FAILURE("virtio-console-invalid-name");
     DO_TEST_FAILURE("virtio-console-invalid-path");
+    DO_TEST("memtune");
+    DO_TEST_FAILURE("memtune-unsupported-params");
 
     /* Address allocation tests */
     DO_TEST("addr-single-sata-disk");
-- 
2.52.0

Reply via email to