From 81180378201111292d23389a39a2e0cf05dca7ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 24 Jan 2014 06:45:17 +0100 Subject: [PATCH 1/7] dispvm: kill all process after populating caches Do not longer rely on killing X server. --- misc/dispvm-prerun.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/misc/dispvm-prerun.sh b/misc/dispvm-prerun.sh index d9db237..01ab6fe 100755 --- a/misc/dispvm-prerun.sh +++ b/misc/dispvm-prerun.sh @@ -30,6 +30,7 @@ ps ax > /tmp/dispvm-prerun-proclist.log echo "Closing windows..." /usr/lib/qubes/close-window `xwininfo -root -children|tail -n +7 |awk '{print $1}'` sleep 1 +fuser -vkm /rw if [ -e /rw/home/user/.qubes-dispvm-customized ]; then cp -af /rw/home/user /home/ From 06a0d30d50ce4ea266532c06ef24880bf5363c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Fri, 24 Jan 2014 06:46:18 +0100 Subject: [PATCH 2/7] dispvm: start gui agent early, do not kill Xorg Now gui agent support reconnecting to guid. --- vm-systemd/prepare-dvm.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vm-systemd/prepare-dvm.sh b/vm-systemd/prepare-dvm.sh index ffa25fe..f59f06b 100755 --- a/vm-systemd/prepare-dvm.sh +++ b/vm-systemd/prepare-dvm.sh @@ -6,19 +6,21 @@ possibly_run_save_script() if [ -z "$ENCODED_SCRIPT" ] ; then return ; fi echo $ENCODED_SCRIPT|perl -e 'use MIME::Base64 qw(decode_base64); local($/) = undef;print decode_base64()' >/tmp/qubes-save-script chmod 755 /tmp/qubes-save-script - Xorg -config /etc/X11/xorg-preload-apps.conf :0 & while ! [ -S /tmp/.X11-unix/X0 ]; do sleep 0.5; done DISPLAY=:0 su - user -c /tmp/qubes-save-script - killall Xorg Xorg.bin } -if qubesdb-read /qubes-save-request 2>/dev/null ; then +if true; then if [ -L /home ]; then rm /home mkdir /home fi mount --bind /home_volatile /home touch /etc/this-is-dvm + systemctl --ignore-dependencies start qubes-gui-agent.service + while ! xenstore-read qubes-save-request 2>/dev/null ; do + usleep 10 + done mount /rw possibly_run_save_script umount /rw From 5c4e88a76535680cbf7971109a07814695c85ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 4 Mar 2015 01:48:11 +0100 Subject: [PATCH 3/7] dispvm: close only visible windows during DispVM preparation Closing some invisible window can cause e.g. Firefox crash. Send the message to visible windows and others should be cleaned up by the application. --- misc/close-window.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/misc/close-window.c b/misc/close-window.c index 071527c..645cd7a 100644 --- a/misc/close-window.c +++ b/misc/close-window.c @@ -15,15 +15,26 @@ int close_window(Display *d, XID window) { return XSendEvent(ev.display, ev.window, True, 0, (XEvent *) & ev); } +int is_window_visible(Display *d, XID window) { + XWindowAttributes xwa; + + if (!XGetWindowAttributes(d, window, &xwa)) + return 0; + return xwa.map_state == IsViewable; +} + int main(int argc, char **argv) { int i; Display *d; + XID w; d = XOpenDisplay(NULL); if (!d) exit(1); for (i=1; i Date: Wed, 4 Mar 2015 01:52:18 +0100 Subject: [PATCH 4/7] Move mounting /rw and /home to separate service Many services depended on misc-post only because this was where /home gets mounted. Move that to separate service, started earlier. --- misc/dispvm-prerun.sh | 6 ---- rpm_spec/core-vm.spec | 6 ++-- vm-systemd/misc-post.sh | 33 -------------------- vm-systemd/mount-home.sh | 48 +++++++++++++++++++++++++++++ vm-systemd/prepare-dvm.sh | 7 ----- vm-systemd/qubes-misc-post.service | 2 +- vm-systemd/qubes-mount-home.service | 13 ++++++++ 7 files changed, 66 insertions(+), 49 deletions(-) create mode 100644 vm-systemd/mount-home.sh create mode 100644 vm-systemd/qubes-mount-home.service diff --git a/misc/dispvm-prerun.sh b/misc/dispvm-prerun.sh index 01ab6fe..91b90cb 100755 --- a/misc/dispvm-prerun.sh +++ b/misc/dispvm-prerun.sh @@ -32,10 +32,4 @@ echo "Closing windows..." sleep 1 fuser -vkm /rw -if [ -e /rw/home/user/.qubes-dispvm-customized ]; then - cp -af /rw/home/user /home/ -else - cat /etc/dispvm-dotfiles.tbz | tar -xjf- --overwrite -C /home/user --owner user 2>&1 >>/tmp/dispvm-dotfiles-errors.log -fi - echo done. diff --git a/rpm_spec/core-vm.spec b/rpm_spec/core-vm.spec index 4461d5f..2565bbf 100644 --- a/rpm_spec/core-vm.spec +++ b/rpm_spec/core-vm.spec @@ -546,6 +546,7 @@ The Qubes core startup configuration for SystemD init. /lib/systemd/system/qubes-dvm.service /lib/systemd/system/qubes-misc-post.service /lib/systemd/system/qubes-firewall.service +/lib/systemd/system/qubes-mount-home.service /lib/systemd/system/qubes-netwatcher.service /lib/systemd/system/qubes-network.service /lib/systemd/system/qubes-sysinit.service @@ -561,6 +562,7 @@ The Qubes core startup configuration for SystemD init. /usr/lib/qubes/init/network-proxy-setup.sh /usr/lib/qubes/init/misc-post.sh /usr/lib/qubes/init/misc-post-stop.sh +/usr/lib/qubes/init/mount-home.sh /usr/lib/qubes/init/qubes-sysinit.sh /usr/lib/qubes/init/ModemManager.service /usr/lib/qubes/init/NetworkManager.service @@ -580,7 +582,7 @@ The Qubes core startup configuration for SystemD init. %post systemd -for srv in qubes-dvm qubes-sysinit qubes-misc-post qubes-netwatcher qubes-network qubes-firewall qubes-updates-proxy qubes-qrexec-agent; do +for srv in qubes-dvm qubes-sysinit qubes-misc-post qubes-mount-home qubes-netwatcher qubes-network qubes-firewall qubes-updates-proxy qubes-qrexec-agent; do /bin/systemctl --no-reload enable $srv.service 2> /dev/null done @@ -648,6 +650,6 @@ if [ "$1" != 0 ] ; then exit 0 fi -for srv in qubes-dvm qubes-sysinit qubes-misc-post qubes-netwatcher qubes-network qubes-qrexec-agent; do +for srv in qubes-dvm qubes-sysinit qubes-misc-post qubes-mount-home qubes-netwatcher qubes-network qubes-qrexec-agent; do /bin/systemctl disable $srv.service do diff --git a/vm-systemd/misc-post.sh b/vm-systemd/misc-post.sh index 27b07e2..d3717d3 100755 --- a/vm-systemd/misc-post.sh +++ b/vm-systemd/misc-post.sh @@ -22,39 +22,6 @@ fi # qubesdb-read fails INTERFACE=eth0 /usr/lib/qubes/setup-ip -if [ -e /dev/xvdb -a ! -e /etc/this-is-dvm ] ; then - resize2fs /dev/xvdb 2> /dev/null || echo "'resize2fs /dev/xvdb' failed" - tune2fs -m 0 /dev/xvdb - mount /rw - - if ! [ -d /rw/home ] ; then - echo - echo "--> Virgin boot of the VM: Linking /home to /rw/home" - - mkdir -p /rw/config - touch /rw/config/rc.local - touch /rw/config/rc.local-early - - mkdir -p /rw/home - cp -a /home.orig/user /rw/home - - mkdir -p /rw/usrlocal - cp -a /usr/local.orig/* /rw/usrlocal - - touch /var/lib/qubes/first-boot-completed - fi - # Chown home if user UID have changed - can be the case on template switch - HOME_USER_UID=`ls -dn /rw/home/user | awk '{print $3}'` - if [ "`id -u user`" -ne "$HOME_USER_UID" ]; then - find /rw/home/user -uid "$HOME_USER_UID" -print0 | xargs -0 chown user:user - fi - if [ -L /home ]; then - rm /home - mkdir /home - fi - mount /home -fi - [ -x /rw/config/rc.local ] && /rw/config/rc.local # Start services which haven't own proper systemd unit: diff --git a/vm-systemd/mount-home.sh b/vm-systemd/mount-home.sh new file mode 100644 index 0000000..3307551 --- /dev/null +++ b/vm-systemd/mount-home.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +resize2fs /dev/xvdb 2> /dev/null || echo "'resize2fs /dev/xvdb' failed" +tune2fs -m 0 /dev/xvdb +mount /rw + +if ! [ -d /rw/home ] ; then + echo + echo "--> Virgin boot of the VM: Populating /rw/home" + + mkdir -p /rw/config + touch /rw/config/rc.local + touch /rw/config/rc.local-early + + mkdir -p /rw/home + cp -a /home.orig/user /rw/home + + mkdir -p /rw/usrlocal + cp -a /usr/local.orig/* /rw/usrlocal + + touch /var/lib/qubes/first-boot-completed +fi + +# Chown home if user UID have changed - can be the case on template switch +HOME_USER_UID=`ls -dn /rw/home/user | awk '{print $3}'` +if [ "`id -u user`" -ne "$HOME_USER_UID" ]; then + find /rw/home/user -uid "$HOME_USER_UID" -print0 | xargs -0 chown user:user +fi + +# Old Qubes versions had symlink /home -> /rw/home; now we use mount --bind +if [ -L /home ]; then + rm /home + mkdir /home +fi + +if [ -e /var/run/qubes-service/qubes-dvm ]; then + mount --bind /home_volatile /home + touch /etc/this-is-dvm + + #If user have customized DispVM settings, use its home instead of default dotfiles + if [ -e /rw/home/user/.qubes-dispvm-customized ]; then + cp -af /rw/home/user /home/ + else + cat /etc/dispvm-dotfiles.tbz | tar -xjf- --overwrite -C /home/user --owner user 2>&1 >/tmp/dispvm-dotfiles-errors.log + fi +else + mount /home +fi diff --git a/vm-systemd/prepare-dvm.sh b/vm-systemd/prepare-dvm.sh index f59f06b..ac1022f 100755 --- a/vm-systemd/prepare-dvm.sh +++ b/vm-systemd/prepare-dvm.sh @@ -11,17 +11,10 @@ possibly_run_save_script() } if true; then - if [ -L /home ]; then - rm /home - mkdir /home - fi - mount --bind /home_volatile /home - touch /etc/this-is-dvm systemctl --ignore-dependencies start qubes-gui-agent.service while ! xenstore-read qubes-save-request 2>/dev/null ; do usleep 10 done - mount /rw possibly_run_save_script umount /rw dmesg -c >/dev/null diff --git a/vm-systemd/qubes-misc-post.service b/vm-systemd/qubes-misc-post.service index 8aec208..8450a12 100644 --- a/vm-systemd/qubes-misc-post.service +++ b/vm-systemd/qubes-misc-post.service @@ -1,6 +1,6 @@ [Unit] Description=Qubes misc post-boot actions -After=qubes-dvm.service +After=qubes-dvm.service qubes-mount-home.service [Service] Type=oneshot diff --git a/vm-systemd/qubes-mount-home.service b/vm-systemd/qubes-mount-home.service new file mode 100644 index 0000000..93b3f93 --- /dev/null +++ b/vm-systemd/qubes-mount-home.service @@ -0,0 +1,13 @@ +[Unit] +Description=Mount /rw and /home, initialize them if needed +Before=qubes-gui-agent.service + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/lib/qubes/init/mount-home.sh +ExecStop=/sbin/fuser -kMm /home ; /bin/umount /home +ExecStopPost=-/bin/umount /rw + +[Install] +WantedBy=multi-user.target From 4303b7dc52d1e4b2edacb5056b6da146cb7dc4a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 4 Mar 2015 02:08:22 +0100 Subject: [PATCH 5/7] dispvm: use qubes.WaitForSession to wait for gui-agent startup --- vm-systemd/prepare-dvm.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/vm-systemd/prepare-dvm.sh b/vm-systemd/prepare-dvm.sh index ac1022f..a8d0c07 100755 --- a/vm-systemd/prepare-dvm.sh +++ b/vm-systemd/prepare-dvm.sh @@ -6,15 +6,11 @@ possibly_run_save_script() if [ -z "$ENCODED_SCRIPT" ] ; then return ; fi echo $ENCODED_SCRIPT|perl -e 'use MIME::Base64 qw(decode_base64); local($/) = undef;print decode_base64()' >/tmp/qubes-save-script chmod 755 /tmp/qubes-save-script - while ! [ -S /tmp/.X11-unix/X0 ]; do sleep 0.5; done DISPLAY=:0 su - user -c /tmp/qubes-save-script } if true; then - systemctl --ignore-dependencies start qubes-gui-agent.service - while ! xenstore-read qubes-save-request 2>/dev/null ; do - usleep 10 - done + echo user | /bin/sh /etc/qubes-rpc/qubes.WaitForSession possibly_run_save_script umount /rw dmesg -c >/dev/null From 57be9101355e95ceda5ee637d22decccafc8bff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 4 Mar 2015 02:09:18 +0100 Subject: [PATCH 6/7] dispvm: include memory caches in "used memory" notification Also make the code more readable. --- vm-systemd/prepare-dvm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm-systemd/prepare-dvm.sh b/vm-systemd/prepare-dvm.sh index a8d0c07..4fc23d7 100755 --- a/vm-systemd/prepare-dvm.sh +++ b/vm-systemd/prepare-dvm.sh @@ -15,7 +15,7 @@ if true; then umount /rw dmesg -c >/dev/null free | grep Mem: | - (read a b c d ; qubesdb-write /qubes-used-mem $c) + (read label total used free shared buffers cached; qubesdb-write /qubes-used-mem $[ $used + $cached ]) # give dom0 time to read some entries, when done it will shutdown qubesdb, # so wait for it qubesdb-watch /stop-qubesdb From 3687c4e622bb34cf923005e28fd7d4926acaaad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 4 Mar 2015 02:10:28 +0100 Subject: [PATCH 7/7] dispvm: do not restart qubesdb-daemon, use watch instead qubesdb-daemon will handle reconnection by itself. --- vm-systemd/prepare-dvm.sh | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/vm-systemd/prepare-dvm.sh b/vm-systemd/prepare-dvm.sh index 4fc23d7..04a9e1f 100755 --- a/vm-systemd/prepare-dvm.sh +++ b/vm-systemd/prepare-dvm.sh @@ -14,18 +14,13 @@ if true; then possibly_run_save_script umount /rw dmesg -c >/dev/null + qubesdb-watch /qubes-restore-complete & + watch_pid=$! free | grep Mem: | (read label total used free shared buffers cached; qubesdb-write /qubes-used-mem $[ $used + $cached ]) - # give dom0 time to read some entries, when done it will shutdown qubesdb, - # so wait for it - qubesdb-watch /stop-qubesdb - # just to make sure - systemctl stop qubes-db.service - # we're still running in DispVM template echo "Waiting for save/restore..." - # the service will start only after successful restore - systemctl start qubes-db.service + qubesdb-read /qubes-restore-complete || wait $watch_pid echo Back to life. fi