From e8c4089a3ebf4045c7555a7bd545731605252a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20V=C3=A4th?= Date: Sat, 24 Aug 2019 12:16:42 +0200 Subject: [PATCH] Support writeback of incompressible/idle pages and writeback_limit --- ChangeLog | 5 ++++ openrc/conf.d/zram-init | 14 +++++++++++ openrc/init.d/zram-init | 8 ++++-- sbin/zram-init | 54 +++++++++++++++++++++++++++++++++++------ zsh/_zram-init | 3 +++ 5 files changed, 75 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 58be515..4a2e9ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ # ChangeLog for zram-init: +*zram-init-9.0: + Martin Väth : + - Support writeback of incompressible/idle pages and writeback_limit + - Finally suppress the annoying output of the logger path + *zram-init-8.2: Edlund Scott : - Fix variable typos and shell style diff --git a/openrc/conf.d/zram-init b/openrc/conf.d/zram-init index 5c7f048..89ffb01 100644 --- a/openrc/conf.d/zram-init +++ b/openrc/conf.d/zram-init @@ -16,6 +16,11 @@ num_devices=2 # size0, size1, ... are the variables for the sizes (in MB) # mlim0, mlim1, ... are the variables for the maximal uncompressed memory (MB) # back0, back1, ... are the variables for the backup device +# icmp0, icmp1, ... are the flags (if nonempty) for writing incompressible +# pages to the backup device (requires setting back*) +# idle0, idle1, ... are the flags (in nonempty) for writing idle pages to the +# backup device (requires setting back*) +# wlim0, wlim1, ... set the writeback_limit for idle pages (implies idle*) # maxs0, maxs1, ... are the variables for the maximal (parallel) streams # algo0, algo1, ... are the variables for the compression algorithms # flag0, flag1, ... are the variables for the flags @@ -52,6 +57,9 @@ flag0= # The default "16383" is fine for us size0=`LC_ALL=C free -m | awk '/^Mem:/{print int($2/2)}'` mlim0= # no hard memory limit back0= # no backup device +icmp0= # no incompressible page writing to backup device +idle0= # no idle page writing to backup device +wlim0= # no writeback_limit for idle page writing for backup device notr0= # keep the default on linux-3.15 or newer maxs0=1 # maximum number of parallel processes for this device algo0=zstd # zstd (since linux-4.18), lz4 (since linux-3.15), or lzo. @@ -69,6 +77,9 @@ flag1=ext4 size1=2048 mlim1= # no hard memory limit back1= # no backup device +icmp1= # no incompressible page writing to backup device +idle1= # no idle page writing to backup device +wlim1= # no writeback_limit for idle page writing for backup device opts1="strictatime,nosuid,nodev,noexec" # e.g. "relatime" or "noatime" are also reasonable choices mode1=1777 owgr1= # No reason to change the default "root:root" @@ -85,6 +96,9 @@ flag2=ext2 size2=1024 mlim2= # no hard memory limit back2= # no backup device +icmp2= # no incompressible page writing to backup device +idle2= # no idle page writing to backup device +wlim2= # no writeback_limit for idle page writing for backup device opts2=relatime # e.g. "noatime" or "strictatime" are also reasonable choices mode2=1777 owgr2= # No reason to change the default "root:root" diff --git a/openrc/init.d/zram-init b/openrc/init.d/zram-init index eaaeccc..a6ec291 100755 --- a/openrc/init.d/zram-init +++ b/openrc/init.d/zram-init @@ -7,9 +7,10 @@ depend() { ZramInit() { set -- ${1+"$@"} -D "$num_devices" \ - ${mlim:+-S "$mlim"} ${back:+-b "$back"} ${notr:+-T} \ + ${mlim:+-S "$mlim"} ${back:+-b "$back"} \ + ${icmp:+-I} ${idle:+-w} ${wlim:+-W "$wlim"} \ ${maxs:+-s "$maxs"} ${algo:+-a "$algo"} \ - ${labl:+-L "$labl"} ${uuid:+-U "$uuid"} + ${labl:+-L "$labl"} ${uuid:+-U "$uuid"} ${notr:+-T} [ -z "${args:++}" ] || eval 'set -- "$@" '"$args" if [ x"$fstype" = x'swap' ] then einfo "Swap->zram$2" @@ -50,6 +51,9 @@ ZramIgnore() { size=\${size$1:-0} mlim=\${mlim$1} back=\${back$1} + icmp=\${icmp$1} + idle=\${idle$1} + wlim=\${wlim$1} maxs=\${maxs$1-} algo=\${algo$1-} flag=\${flag$1-} diff --git a/sbin/zram-init b/sbin/zram-init index 6092428..449f379 100755 --- a/sbin/zram-init +++ b/sbin/zram-init @@ -5,7 +5,7 @@ Echo() { printf '%s\n' "$*" } -if command -v logger +if command -v logger >/dev/null 2>&1 then EchoLog() { Echo "$*" logger "$*" @@ -52,10 +52,12 @@ IsNumeric() { } Usage() { - Echo "Usage: ${0##*/} [options] SIZE [DIR] + Echo "Usage: ${0##*/} [options] SIZE|write [DIR] Prepare a zram device and use it as swap (resp. mount it under DIR). SIZE is the maximal size in megabytes. For umounting/freeing the zram device, use SIZE=0. +When using \"write\" (or anything else starting with \"w\") an idle writeback +is forced (only makes sense if previously initialized with -w or -W LIMIT). If DIR is - then only a filesystem is created in /dev/zram\$DEV (or the device is removed if SIZE is 0) but it is not mounted (options -o -c -m -T take no effect in this case, of course). @@ -71,6 +73,9 @@ An empty argument means the same as if the option is not specified. -s NUM Use up to NUM parallel compression streams for the device -S MAX Use maximally MAX megabytes of uncompressed memory for the device -b DEV Use DEV as backing device +-I If combined with -b DEV, store incompressible pages to backing device +-w If combined with -b DEV, enable idle writeback to backing device +-W LIMIT As -w but additionally set writeback_limit to LIMIT * 4kB. -a ALGO Set compression algorithm to ALGO (e.g. zstd, lz4, or lzo) -c OWNER If specified, chown to OWNER (resp. OWNER:GROUP) after mounting. If not specified, the default owner (root:root) is not changed. @@ -123,13 +128,17 @@ tune2fs_opt= zramctl_opt= mem_limit= backing_dev= +writeback=false +writeback_limit= +incompressible=false OPTIND=1 -while getopts 's:S:a:b:c:d:D:m:o:p:t:i:N:L:U:TlkK:M:2:Z:hH' opt +while getopts 's:S:a:b:Ic:d:D:m:o:p:t:i:N:L:U:wW:TlkK:M:2:Z:hH' opt do case $opt in s) streams=$OPTARG;; S) mem_limit=$OPTARG;; a) algo=$OPTARG;; b) backing_dev=$OPTARG;; + I) incompressible=:;; c) owgr=$OPTARG;; d) dev=$OPTARG;; D) num=$OPTARG;; @@ -141,6 +150,9 @@ do case $opt in N) inodes=$OPTARG;; L) label=$OPTARG;; U) uuid=$OPTARG;; + w) writeback=:;; + W) writeback=: + writeback_limit=$OPTARG;; T) discard=false;; l) zramctl=false;; k) keep=:;; @@ -163,7 +175,22 @@ fi : "${dev:=0}" "${prio:=16383}" "${fstype:=ext4}" IsNumeric "$dev" || Fatal "device $dev is not numeric" + +devnode=/dev/zram$dev +zclass=/sys/class/zram-control +block=/sys/block/zram$dev + +case ${1:-0} in +w*) + SysCtlN idle "$block/writeback" || \ + Fatal "failed to idle writeback zram$dev" + exit;; +esac + IsNumeric "${1:-0}" || Fatal "size $1 is not numeric" +IsNumeric "${mem_limit:-0}" || Fatal "mem_limit $mem_limit is not numeric" +IsNumeric "${writeback_limit:-0}" || \ + Fatal "writeback_limit $writeback_limit is not numeric" umount=: if [ ${1:-0} -ne 0 ] @@ -187,9 +214,6 @@ then swap=false fi fi -devnode=/dev/zram$dev -zclass=/sys/class/zram-control - HotAdd() { while : do curradd= @@ -229,7 +253,6 @@ then $umount && exit keep=: } fi -block=/sys/block/zram$dev if ! $zramctl || [ -n "$mem_limit" ] || [ -n "${backing_dev:++}" ] then test -d "$block" || Fatal "cannot find $block" fi @@ -257,6 +280,7 @@ fi $umount && exit $status test -b "$devnode" || HotAdd + if $zramctl && [ -z "${backing_dev:++}" ] then eval "set -- a $zramctl_opt" shift @@ -271,6 +295,22 @@ else [ -z "$streams" ] || SysCtl "$streams" "$block/max_comp_streams" || \ [ -z "${backing_dev:++}" ] || \ SysCtlN "$backing_dev" "$block/backing_dev" || \ Warning "failed to set zram$dev backing_dev" + ! $incompressible || SysCtlN huge "$block/write" || \ + Warning "failed to set zram$dev incompressible writeback" + ! $writeback || InitWriteback() { + SysCtlN all "$block/idle" || { + Warning "failed to set zram$dev idle writeback" + return + } + [ -n "${writeback_limit:++}" ] || return 0 + SysctlN 1 "$block/writeback_limit_enable" || { + Warning "failed to enable writeback_limit for zram$dev" + return + } + SysctlN "$writeback_limit" "$block/writeback_limit" || \ + Warning "failed to set writeback_limit $writeback_limit for zram$dev" +} + ! $writeback || InitWriteback SysCtl "$size" "$block/disksize" || Fatal "cannot set zram$dev size" fi [ -z "$mem_limit" ] || SysCtl "$mem_limit" "$block/mem_limit" || \ diff --git a/zsh/_zram-init b/zsh/_zram-init index 883e249..df091b0 100644 --- a/zsh/_zram-init +++ b/zsh/_zram-init @@ -5,6 +5,9 @@ _arguments -s -S -A '-*' : \ '(2 -t -c -m -o)-p+[use specified priority for swap]:priority for swap:(0 1 16383 -)' \ '(-p)-t+[use specified filesystem type]:filesystem type:(ext2 ext4 btrfs)' \ '-b+[use specifed device as backing device]:device:_files -g "*(-%b,-/)"' \ +'-I[enable incompressible writeback on backing device]' \ +'-w[enable idle writeback on backing device]' \ +'-W+[use specifed number (times 4kB) as writeback_limit]:4kB writeback_limit:(50 100 300 512 2048 4096 6144 8192 16384)' \ '-D+[use specifed number of devices for modprobe]:number of devices:(1)' \ '-c+[chown to specified owner]:owner\:group:(nobody\:nogroup)' \ '-m+[chmod to specified mode]:mode:(1777 755 770)' \