summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile34
-rwxr-xr-xfirestart.redux57
-rwxr-xr-xsrc/firefox-io-slayer-redux95
-rwxr-xr-xsrc/firefox@.service.in19
-rwxr-xr-xsrc/generate-firefox-unit51
-rw-r--r--src/ioslay@.service5
-rwxr-xr-xsrc/sliceweasel.lib.sh3
8 files changed, 256 insertions, 9 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..704aefd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
/firefox\@.service
diff --git a/Makefile b/Makefile
index bcc1005..50adaed 100644
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,32 @@
1BINDIR = /usr/local/bin 1BINDIR = /usr/local/bin
2BINARIES = firestart firestartx $(addprefix src/,sliceweasel.lib.sh firefox-io-slayer ioslay-firefox) 2BINARIES = firestart firestartx $(addprefix src/,sliceweasel.lib.sh firefox-io-slayer-redux ioslay-firefox)
3SUDO != [ "$$(id -u)" = 0 ] || echo sudo
4 3
5.PHONY: install install-bin 4ifeq ($(shell id -u),0)
5# Prevent running as root
6.PHONY: install-bin
7all:
8install-bin:
9 install $(BINARIES) -t $(BINDIR)
10else
11
12.PHONY: install install-bin start stop restart
13
14firefox@.service: src/firefox@.service.in src/generate-firefox-unit
15 ./src/generate-firefox-unit $< $@
16
17install: install-bin firefox@.service
18 systemctl --user link ./firefox@.service
19 systemctl --user link ./src/ioslay@.service
20 systemctl --user daemon-reload
21
22start: install
23 systemctl --user start "firefox@$$DISPLAY"
6 24
7install: install-bin 25stop:
8 systemctl --user restart ioslay 26 systemctl --user stop firefox@$$DISPLAY ioslay@$$DISPLAY
9 27
10uninstall-units: 28restart: stop start
11 systemctl --user disable ioslay
12 29
13install-bin: 30install-bin:
14 $(SUDO) install $(BINARIES) -t $(BINDIR) 31 sudo $(MAKE) -$(MAKEFLAGS) $@
32endif
diff --git a/firestart.redux b/firestart.redux
new file mode 100755
index 0000000..59d8f8a
--- /dev/null
+++ b/firestart.redux
@@ -0,0 +1,57 @@
1#!/bin/bash
2
3die() { printf "%s: Error: %s\n" "$0" "$*" >&2; exit 1; }
4
5# Test DEVICE WRITE OPS BY WRITEOPS
6test_write_ops()
7{
8 if ! [ -e "$1" ]
9 then
10 mkdir -p "$(dirname "$1")"
11 sync
12 begin=$(date +%s%N)
13 dd if=/dev/urandom of="$DIR"/urandom.out bs=1M count=300
14 sync
15 end=$(date +%s%N)
16 ops=$(( (end - begin) / 1000000000 ))
17 rm "$DIR"/urandom.out
18 echo "$ops" > "$1"
19 fi
20 cat "$1"
21}
22
23CMD=firefox
24UNIT=$CMD
25DIR=~/.mozilla
26READ_OPS=1G
27WRITE_OPS=$READ_OPS
28CONFDIR=$HOME/.config/firestart
29
30if [ -e "$CONFDIR"/conf ]
31then
32 . "$CONFDIR"/conf
33fi
34
35WRITE_OPS=$(test_write_ops "$CONFDIR"/diskspeed.dat)
36WRITE_OPS=${WRITE_OPS%.*}
37READ_OPS=$WRITE_OPS
38
39[ -e "$DIR" ] || die "does not exist: $DIR"
40[ -d "$DIR" ] || die "not a directory: $DIR"
41
42DEV=$(echo $(findmnt --target "$DIR" -o MAJ:MIN -n))
43[ "$DEV" ] || die "could not determine backing device for $DIR"
44
45IOReadIOPSMax="$DEV $READ_OPS"
46IOWriteIOPSMax="$DEV $WRITE_OPS"
47
48sed -e "s/^IOReadIOPSMax *=.*/IOReadIOPSMax = $IOReadIOPSMax/" \
49 -e "s/^IOWriteIOPSMax *=.*/IOWriteIOPSMax = $IOWriteIOPSMax/" \
50 < firefox@.service.in > firefox@.service
51
52set -x
53
54systemctl --user link "$PWD"/firefox@.service
55systemctl --user link "$PWD"/ioslay@.service
56systemctl --user daemon-reload
57systemctl --user start "firefox@$DISPLAY"
diff --git a/src/firefox-io-slayer-redux b/src/firefox-io-slayer-redux
new file mode 100755
index 0000000..fe54e37
--- /dev/null
+++ b/src/firefox-io-slayer-redux
@@ -0,0 +1,95 @@
1#!/bin/bash
2
3DISPLAY=$1
4
5if [ -e /usr/lib/bash/sleep ]
6then
7 enable -f /usr/lib/bash/sleep sleep
8fi
9
10export NOTICE=y
11noticeLOG() { [ "$NOTICE" ] || return; echo "Notice: $*" >&2; }
12debugLOG() { [ "$DBG" ] || return; echo "Debug: $*" >&2; }
13
14. sliceweasel.lib.sh
15
16vkill()
17{
18 if [ $# = 0 ]
19 then
20 return
21 fi
22 (
23 if [ "$(id -u)" = 0 ]
24 then sudo=
25 else sudo=sudo
26 fi
27 set -x
28 ps u "$@"
29 $sudo kill "$@"
30 )
31}
32
33slay_slayer()
34{
35 if [ "$ioslay" ]
36 then
37 children=$(for pid in $ioslay; do pgrep -P $ioslay; done)
38 grandchildren=$(for pid in $children; do pgrep -P $pid; done)
39 vkill $ioslay $children $grandchildren
40 fi
41}
42
43group_procs=$(get_firefox_cgroup_procs)
44
45ioslay=
46lastprocs=
47SIGNALLED=
48trap 'SIGNALLED=y' SIGINT SIGTERM SIGHUP
49while [ ! "$SIGNALLED" ]
50do
51 if ! [ -e "$group_procs" ]
52 then
53 [ "$warned" ] || echo "Warning: firefox not running or cgroup not found" >&2
54 warned=y
55 else
56 if [ "$warned" ]
57 then
58 echo "Found firefox cgroup: $group_procs" >&2
59 warned=
60 fi
61 read -N 1000100 procs < "$group_procs"
62 if [ "$procs" ]
63 then
64 set --
65 for pid in $procs
66 do
67 read comm < /proc/$pid/comm
68 case "$comm" in
69 'Isolated Web Content' | 'Web Content' | 'Isolated Web Co')
70 set -- "$@" "$pid"
71 debugLOG "accept /proc/$pid/comm $comm"
72 ;;
73 *)
74 debugLOG "reject /proc/$pid/comm $comm"
75 esac
76 done
77
78 # echo "pids: ($*|$(echo $procs))" >&2
79 if [ "$lastargs" != "$*" ]
80 then
81 slay_slayer
82 wait $ioslay
83 if [ $# -gt 0 ]
84 then
85 ioslay-firefox "$@" &
86 ioslay=$!
87 noticeLOG "Launched ioslay-firefox[$ioslay] $*"
88 fi
89 fi
90 lastargs=$*
91 fi
92 fi
93 sleep 1
94done
95slay_slayer
diff --git a/src/firefox@.service.in b/src/firefox@.service.in
new file mode 100755
index 0000000..e3c0329
--- /dev/null
+++ b/src/firefox@.service.in
@@ -0,0 +1,19 @@
1[Unit]
2Description = Firefox
3# Requires=ioslay@%I
4# Requires=pulseaudio.socket # require X11 somehow
5ConditionUser = !root # seems reasonable
6ConditionEnvironment = DISPLAY
7
8[Service]
9ExecStartPre = /usr/bin/systemctl --user start ioslay@%I
10ExecStart = /usr/local/bin/firefox
11Restart = on-failure
12PassEnvironment = DISPLAY XAUTHORITY
13MemoryMax = 50%
14IOReadIOPSMax =
15IOWriteIOPSMax =
16
17[Install]
18Also=ioslay@.service
19WantedBy = default.target # make an X11 user target?
diff --git a/src/generate-firefox-unit b/src/generate-firefox-unit
new file mode 100755
index 0000000..c285ffc
--- /dev/null
+++ b/src/generate-firefox-unit
@@ -0,0 +1,51 @@
1#!/bin/bash
2
3INPUT_FILE=$1
4OUTPUT_FILE=$2
5
6die() { printf "%s: Error: %s\n" "$0" "$*" >&2; exit 1; }
7
8# Test DEVICE WRITE OPS BY WRITEOPS
9test_write_ops()
10{
11 if ! [ -e "$1" ]
12 then
13 mkdir -p "$(dirname "$1")"
14 sync
15 begin=$(date +%s%N)
16 dd if=/dev/urandom of="$DIR"/urandom.out bs=1M count=300
17 sync
18 end=$(date +%s%N)
19 ops=$(( (end - begin) / 1000000000 ))
20 rm "$DIR"/urandom.out
21 echo "$ops" > "$1"
22 fi
23 cat "$1"
24}
25
26DIR=~/.mozilla
27READ_OPS=1G
28WRITE_OPS=$READ_OPS
29CONFDIR=$HOME/.config/firestart
30
31if [ -e "$CONFDIR"/conf ]
32then
33 . "$CONFDIR"/conf
34fi
35
36WRITE_OPS=$(test_write_ops "$CONFDIR"/diskspeed.dat)
37WRITE_OPS=${WRITE_OPS%.*}
38READ_OPS=$WRITE_OPS
39
40[ -e "$DIR" ] || die "does not exist: $DIR"
41[ -d "$DIR" ] || die "not a directory: $DIR"
42
43DEV=$(echo $(findmnt --target "$DIR" -o MAJ:MIN -n))
44[ "$DEV" ] || die "could not determine backing device for $DIR"
45
46IOReadIOPSMax="$DEV $READ_OPS"
47IOWriteIOPSMax="$DEV $WRITE_OPS"
48
49sed -e "s/^IOReadIOPSMax *=.*/IOReadIOPSMax = $IOReadIOPSMax/" \
50 -e "s/^IOWriteIOPSMax *=.*/IOWriteIOPSMax = $IOWriteIOPSMax/" \
51 < "$INPUT_FILE" > "$OUTPUT_FILE"
diff --git a/src/ioslay@.service b/src/ioslay@.service
new file mode 100644
index 0000000..1a00bd4
--- /dev/null
+++ b/src/ioslay@.service
@@ -0,0 +1,5 @@
1[Unit]
2Description = Kill firefox when it spins the disk
3
4[Service]
5ExecStart = /usr/local/bin/firefox-io-slayer-redux %I
diff --git a/src/sliceweasel.lib.sh b/src/sliceweasel.lib.sh
index 3b42a61..7f70e08 100755
--- a/src/sliceweasel.lib.sh
+++ b/src/sliceweasel.lib.sh
@@ -112,7 +112,8 @@ get_firefox_cgroup_procs()
112{ 112{
113 uid=$(get_uid) 113 uid=$(get_uid)
114 [ "$uid" ] || return 114 [ "$uid" ] || return
115 echo /sys/fs/cgroup/user.slice/user-$uid.slice/user@$uid.service/app.slice/firefox.service/cgroup.procs 115 [ "$DISPLAY" ] || return
116 echo /sys/fs/cgroup/user.slice/user-$uid.slice/user@$uid.service/app.slice/app-firefox.slice/firefox@$DISPLAY.service/cgroup.procs
116} 117}
117 118
118get_current_group() 119get_current_group()