From 473b822e0c999b296945a6fbfca5a03cd95a77e8 Mon Sep 17 00:00:00 2001 From: Victor Lopez Date: Tue, 16 Sep 2014 21:25:52 +0200 Subject: [PATCH] Linux VM specific: force minimum init mem to allow scaling up memory Check init_mem and max_mem_size in a single function (merging the previous two) taking into account the minimum init memory that allows the requested maximum memory. Explanation: Linux kernel needs space for memory-related structures created at boot. If init_mem is just 400MB, then max_mem can't balloon above 4.3GB (at which poing it yields "add_memory() failed: -17" messages and apps crash), regardless of the max_mem_size value. Base of Marek's findings and my tests on a 16GB PC, using several processes like: stress -m 1 --vm-bytes 1g --vm-hang 100 result in the following points: init_mem ==> actual max memory 400 4300 700 7554 800 8635 1024 11051 1200 12954 1300 14038 1500 14045 <== probably capped on my 16GB system The actual ratio of max_mem_size/init_mem is surprisingly constant at 10.79 If less init memory is set than that ratio allows, then the set max_mem_size is unreachable and the VM becomes unstable (app crashes) Based on qubes-devel discussion titled "Qubes Dom0 init memory against Xen best practices?" at: https://groups.google.com/d/msg/qubes-devel/VRqkFj1IOtA/UgMgnwfxVSIJ --- qubesmanager/settings.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/qubesmanager/settings.py b/qubesmanager/settings.py index 8dd612d..eb20ac5 100755 --- a/qubesmanager/settings.py +++ b/qubesmanager/settings.py @@ -88,8 +88,8 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog): ###### advanced tab self.__init_advanced_tab__() self.include_in_balancing.stateChanged.connect(self.include_in_balancing_state_changed) - self.connect(self.init_mem, SIGNAL("valueChanged(int)"), self.init_mem_changed) - self.connect(self.max_mem_size, SIGNAL("editingFinished()"), self.max_mem_size_changed) + self.connect(self.init_mem, SIGNAL("editingFinished()"), self.check_mem_changes) + self.connect(self.max_mem_size, SIGNAL("editingFinished()"), self.check_mem_changes) self.drive_path_button.clicked.connect(self.drive_path_button_pressed) ###### firewall tab @@ -450,15 +450,15 @@ class VMSettingsWindow(Ui_SettingsDialog, QDialog): return msg - def init_mem_changed(self, value): - if value > self.max_mem_size.value() and value <= self.max_mem_size.maximum(): - self.max_mem_size.setValue(value) - - - def max_mem_size_changed(self): + def check_mem_changes(self): if self.max_mem_size.value() < self.init_mem.value(): - QMessageBox.warning(None, "Warning!", "Max memory can't be lower than initial memory.
Setting max memory equaling initial memory.") + QMessageBox.warning(None, "Warning!", "Max memory can not be less than initial memory.
Setting max memory to equal initial memory.") self.max_mem_size.setValue(self.init_mem.value()) + # Linux specific limit: init memory must not be below max_mem_size/10.79 in order to allow scaling up to max_mem_size (or else "add_memory() failed: -17" problem) + if self.init_mem.value() * 10 < self.max_mem_size.value(): + QMessageBox.warning(None, "Warning!", "Initial memory can not be less than one tenth Max memory.
Setting initial memory to the minimum allowed value.") + self.init_mem.setValue(self.max_mem_size.value() / 10) + ######### advanced tab