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
This commit is contained in:
Victor Lopez 2014-09-16 21:25:52 +02:00 committed by Marek Marczykowski-Górecki
parent cec7bc3255
commit 473b822e0c

View File

@ -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.<br>Setting max memory equaling initial memory.")
QMessageBox.warning(None, "Warning!", "Max memory can not be less than initial memory.<br>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.<br>Setting initial memory to the minimum allowed value.")
self.init_mem.setValue(self.max_mem_size.value() / 10)
######### advanced tab