From 1f194cbe08b0db8a01bd11d5cc158eff1632b229 Mon Sep 17 00:00:00 2001 From: Marek Marczykowski Date: Fri, 1 Jun 2012 20:59:45 +0200 Subject: [PATCH] dom0: block_cleaner: removes ejected devices from xenstore When device is ejected by some VM (state=6, effectively inactive), it should be removed from xenstore to free slot for some another device. This should be done by libxl toolstack, but not implemented in xen 4.1 - AFAIR done in xen 4.2. --- dom0/aux-tools/block_cleaner_daemon.py | 53 ++++++++++++++++++++++++++ dom0/init.d/qubes_core | 2 + rpm_spec/core-dom0.spec | 2 + 3 files changed, 57 insertions(+) create mode 100755 dom0/aux-tools/block_cleaner_daemon.py diff --git a/dom0/aux-tools/block_cleaner_daemon.py b/dom0/aux-tools/block_cleaner_daemon.py new file mode 100755 index 00000000..76154759 --- /dev/null +++ b/dom0/aux-tools/block_cleaner_daemon.py @@ -0,0 +1,53 @@ +#!/usr/bin/python + +import xen.lowlevel.xs +import time +import subprocess + +xs = xen.lowlevel.xs.xs() + +domain_list = [] + +def setup_watches(): + global domain_list + + new_domain_list = xs.ls('', '/local/domain') + for dom in new_domain_list: + if dom not in domain_list: + print "Adding: %s" % dom + xs.watch('/local/domain/%s/backend/vbd' % dom, int(dom)) + for dom in domain_list: + if dom not in new_domain_list: + print "Removing: %s" % dom + xs.unwatch('/local/domain/%s/backend/vbd' % dom, int(dom)) + domain_list = new_domain_list + +def handle_vbd_state(path): + state = xs.read('', path) + if state == '6': + # Closed state; wait a moment to not interrupt reconnect + time.sleep(0.500) + state = xs.read('', path) + if state == '6': + # If still closed, detach device + path_components = path.split('/') + # /local/domain//backend/vbd///... + vm_xid = path_components[6] + vm_dev = path_components[7] + if vm_xid in domain_list: + subprocess.call('xl', 'block-detach', vm_xid, vm_dev) + +def main(): + + xs.watch('@introduceDomain', 'reload') + xs.watch('@releaseDomain', 'reload') + setup_watches() + while True: + (path, token) = xs.read_watch() + if token == 'reload': + setup_watches() + else: + if path.endswith('/state'): + handle_vbd_state(path) + +main() diff --git a/dom0/init.d/qubes_core b/dom0/init.d/qubes_core index 072f0ac2..b491da6d 100755 --- a/dom0/init.d/qubes_core +++ b/dom0/init.d/qubes_core @@ -53,6 +53,8 @@ start() MEMINFO_DELAY_USEC=100000 /usr/lib/qubes/meminfo-writer $MEM_CHANGE_THRESHOLD_KB $MEMINFO_DELAY_USEC & + /usr/lib/qubes/block_cleaner_daemon.py > /var/log/qubes/block_cleaner.log 2>&1 & + # Reply block events to hide mounted devices from qubes-block list (at first udev run, only / is mounted) udevadm trigger --subsystem-match=block --action=add diff --git a/rpm_spec/core-dom0.spec b/rpm_spec/core-dom0.spec index f6ec33e1..4de15029 100644 --- a/rpm_spec/core-dom0.spec +++ b/rpm_spec/core-dom0.spec @@ -114,6 +114,7 @@ cp aux-tools/qubes-receive-updates $RPM_BUILD_ROOT/usr/lib/qubes/ cp ../misc/block_add_change $RPM_BUILD_ROOT/usr/lib/qubes/ cp ../misc/block_remove $RPM_BUILD_ROOT/usr/lib/qubes/ cp ../misc/block_cleanup $RPM_BUILD_ROOT/usr/lib/qubes/ +cp aux-tools/block_cleaner_daemon.py $RPM_BUILD_ROOT/usr/lib/qubes/ mkdir -p $RPM_BUILD_ROOT/etc/qubes_rpc/policy cp ../qubes_rpc/qubes.Filecopy.policy $RPM_BUILD_ROOT/etc/qubes_rpc/policy/qubes.Filecopy @@ -344,6 +345,7 @@ fi /usr/lib/qubes/block_add_change /usr/lib/qubes/block_remove /usr/lib/qubes/block_cleanup +/usr/lib/qubes/block_cleaner_daemon.py* %attr(4750,root,qubes) /usr/lib/qubes/qfile-dom0-unpacker %attr(770,root,qubes) %dir /var/lib/qubes %attr(770,root,qubes) %dir /var/lib/qubes/vm-templates