ext/services: add automatic migration meminfo-writer=False -> maxmem=0

Migrate meminfo-writer=False service setting to maxmem=0 as a method to
disable dynamic memory management. Remove the service from vm.features
dict in the process.

Additionally, translate any attempt to set the service.meminfo-writer
feature to either setting maxmem=0 or resetting it to the default (which
is memory balancing enabled if supported by given domain). This is to at
least partially not break existing tools using service.meminfo-writer as
a way to control dynamic memory management. This code does _not_ support
reading service.meminfo-writer feature state to get the current state of
dynamic memory management, as it would require synchronizing with all
the factors affecting its value. One of main reasons for migrating to
maxmem=0 approach is to avoid the need of such synchronization.

QubesOS/qubes-issues#4480
This commit is contained in:
Marek Marczykowski-Górecki 2018-11-15 15:02:14 +01:00
parent 62bc462a23
commit 087a02c7f4
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -47,6 +47,20 @@ class ServicesExtension(qubes.ext.Extension):
def on_domain_feature_set(self, vm, event, feature, value, oldvalue=None): def on_domain_feature_set(self, vm, event, feature, value, oldvalue=None):
'''Update /qubes-service/ QubesDB tree in runtime''' '''Update /qubes-service/ QubesDB tree in runtime'''
# pylint: disable=unused-argument # pylint: disable=unused-argument
# TODO: remove this compatibility hack in Qubes 4.1
if feature == 'service.meminfo-writer':
# if someone try to enable meminfo-writer ...
if value:
# ... reset maxmem to default
vm.maxmem = qubes.property.DEFAULT
else:
# otherwise, set to 0
vm.maxmem = 0
# in any case, remove the entry, as it does not indicate memory
# balancing state anymore
del vm.features['service.meminfo-writer']
if not vm.is_running(): if not vm.is_running():
return return
if not feature.startswith('service.'): if not feature.startswith('service.'):
@ -65,8 +79,22 @@ class ServicesExtension(qubes.ext.Extension):
if not feature.startswith('service.'): if not feature.startswith('service.'):
return return
service = feature[len('service.'):] service = feature[len('service.'):]
# this one is excluded from user control
if service == 'meminfo-writer':
return
vm.untrusted_qdb.rm('/qubes-service/{}'.format(service)) vm.untrusted_qdb.rm('/qubes-service/{}'.format(service))
@qubes.ext.handler('domain-load')
def on_domain_load(self, vm, event):
'''Migrate meminfo-writer service into maxmem'''
# pylint: disable=no-self-use,unused-argument
if 'service.meminfo-writer' in vm.features:
# if was set to false, force maxmem=0
# otherwise, simply ignore as the default is fine
if not vm.features['service.meminfo-writer']:
vm.maxmem = 0
del vm.features['service.meminfo-writer']
@qubes.ext.handler('features-request') @qubes.ext.handler('features-request')
def supported_services(self, vm, event, untrusted_features): def supported_services(self, vm, event, untrusted_features):
'''Handle advertisement of supported services''' '''Handle advertisement of supported services'''