summaryrefslogtreecommitdiff
path: root/src/sliceweasel.lib.sh
blob: 7f70e0801e8472c4f334914a3166c3820b762037 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/bin/sh
die()
{
    printf '%s: Error: %s\n' "$0" "$*" >&2
    exit 1
}

get_age()
{
    local mtime now
    mtime=$(stat --format=%Y "$1") || return
    now=$(date +%s) || return
    echo $(( now - mtime ))
}

get_filesystem()
{
    echo /
}

get_total_memory()
{
    free -b | {
        read _
        read _ total _
        echo $total
    }
}

root_write()
{
    $AS_ROOT sh -c 'cat > "$1"' sh "$1" || true
}

join_group()
{
    GROUP_DIR="$1"
    [ -d "$GROUP_DIR" ] || $AS_ROOT mkdir "$GROUP_DIR"
    echo $$ | root_write "$GROUP_DIR"/cgroup.procs
}

add_subtree_controller()
{
    local group="$1" controller="$2" control_file
    control_file="$group/cgroup.subtree_control"

    [ "$group" ] && [ "$controller" ] && [ -d "$group" ] && [ -e "$control_file" ] || return

    case "$group" in
        /sys/fs/cgroup) ;;
        *) add_subtree_controller "$(realpath "$group/..")" "$2" ;;
    esac

    if ! grep -qe "\\b${controller}\\b" "$control_file"
    then
        echo +"$controller" | root_write "$control_file"
    fi
}

set_max()
{
    max_file=$group/$2.max
    if [ ! -e "$max_file" ]
    then
        add_subtree_controller "$1"/.. "$2"
        [ -e "$max_file" ] || return
    fi
    printf '%s\n' "$3" | root_write "$max_file"
}

set_max_ratio()
{
    local group="$1" controller="$2" ratio="$3" limit
    total=$(get_total_$controller)
    n=${ratio%%/*}
    d=${ratio#$n/}
    [ "$d" = "${d%/*}" ] || return
    limit=$(( total * n / d ))
    [ "$limit" ] || return
    [ "$limit" -gt 0 ] || return
    case "$controller" in
        io)
            fsroot=$(get_filesystem "$IO_ROOT_DIR") || return
            # TODO: Do not use lsblk, because it fails to report the correct
            # MOUNTPOINT when a bind mount is present.
            majmin=$(lsblk -o 'MOUNTPOINT,MAJ:MIN' | sed -ne "s?^$fsroot  *??p") || return
            case "$majmin" in
                *:*) ;;
                *) echo "Error: majmin=$majmin" >&2; return 1 ;;
            esac
            set_max "$group" "$controller" "$majmin wbps=$limit rbps=$limit"
        ;;
        *) set_max "$group" "$controller" "$limit"
    esac
}

get_uid()
{
    (
        if [ "$SUDO_USER" ]
        then
            IFS=:
            set -- $(getent passwd "${SUDO_USER}") || return
            echo $3
        else
            id -u
        fi
    )
}

get_firefox_cgroup_procs()
{
    uid=$(get_uid)
    [ "$uid" ] || return
    [ "$DISPLAY" ] || return
    echo /sys/fs/cgroup/user.slice/user-$uid.slice/user@$uid.service/app.slice/app-firefox.slice/firefox@$DISPLAY.service/cgroup.procs
}

get_current_group()
{
    read g < /proc/$$/cgroup
    echo /sys/fs/cgroup/${g#0::/}
}