From 5294f9cc53f2ee318a31f19ed1d0f140eccd7447 Mon Sep 17 00:00:00 2001 From: Frede H Date: Wed, 11 Sep 2024 15:53:24 +0200 Subject: [PATCH] update rules - use auto calc for buffers based on hardware and speed --- .SRCINFO | 9 +++--- 99-usb-sync.rules | 21 ++++++------ PKGBUILD | 12 +++---- udev-usb-sync | 79 ++++++++++++++++++++++++---------------------- udev-usb-sync.conf | 28 ++++++---------- 5 files changed, 72 insertions(+), 77 deletions(-) diff --git a/.SRCINFO b/.SRCINFO index 45235ef..d8b8141 100644 --- a/.SRCINFO +++ b/.SRCINFO @@ -1,18 +1,19 @@ pkgbase = udev-usb-sync pkgdesc = Fine tune write cache and impose buffer limites when USB storage device is plugged - pkgver = 0.8 + pkgver = 0.9 pkgrel = 1 url = https://codeberg.org/wonky/udev-usb-sync install = udev-usb-sync.install arch = any license = MIT depends = hdparm + depends = bc backup = etc/udev-usb-sync/udev-usb-sync.conf source = 99-usb-sync.rules source = udev-usb-sync source = udev-usb-sync.conf - sha256sums = 0c945450f8b472995c27ac4d0b41f333a49a7c8a181827cd57bb80e71194a6f3 - sha256sums = b514e3bf1ea55f5e1dc4f5af46da3b5f9f2409da1efe7b36a11647704faf0a8f - sha256sums = 7cf194b2e3767f8ce4dcbf98b665e46d67624034d5ec0f4cb89f359b677c3687 + sha256sums = 14ff9fa9783f72cb321792ea8a44051d0eb0aaf244edec773d7fa16fdf8dc023 + sha256sums = bdc35135e6f8074890a911a501ca4fb3e6a7888963b51c3a1edb98c23bb62ec2 + sha256sums = ec26baede73e94f9cfab77cd5aa6e0ffebcc413ff657a4e98eae6c9e2145655e pkgname = udev-usb-sync diff --git a/99-usb-sync.rules b/99-usb-sync.rules index 2e92d01..292bdd6 100644 --- a/99-usb-sync.rules +++ b/99-usb-sync.rules @@ -31,16 +31,13 @@ # : @linux-aarhus (Manjaro Forum) # inspired by : @kwg (EndeavourOS Forum) -# rule to disable write cache for usb storage -# requires hdparm to be installed -ACTION=="add|change", KERNEL=="sd[a-z]", ENV{ID_USB_TYPE}=="disk", RUN+="/usr/bin/hdparm -W 0 /dev/%k" +KERNEL!="sd[a-z]", GOTO="usb_limit_write_cache_end" +ENV{ID_USB_TYPE}!="disk", GOTO="usb_limit_write_cache_end" +ACTION!="add|change", GOTO="usb_limit_write_cache_end" -# rules to impose buffer limits on USB devices -# implemented using: /usr/bin/udev-usb-sync -# see configuration: /etc/udev-usb-sync/udev-usb-sync.conf -# Works since Linux 6.2 -ACTION=="add|change", KERNEL=="sd[a-z]", ENV{ID_USB_TYPE}=="disk", RUN+="/usr/bin/udev-usb-sync %k" -ACTION=="add|change", KERNEL=="sd[a-z]", ENV{ID_USB_TYPE}=="disk", ATTRS{speed}=="12", RUN+="/usr/bin/udev-usb-sync %k 12" -ACTION=="add|change", KERNEL=="sd[a-z]", ENV{ID_USB_TYPE}=="disk", ATTRS{speed}=="480", RUN+="/usr/bin/udev-usb-sync %k 480" -ACTION=="add|change", KERNEL=="sd[a-z]", ENV{ID_USB_TYPE}=="disk", ATTRS{speed}=="5000", RUN+="/usr/bin/udev-usb-sync %k 5000" -ACTION=="add|change", KERNEL=="sd[a-z]", ENV{ID_USB_TYPE}=="disk", ATTRS{speed}=="10000", RUN+="/usr/bin/udev-usb-sync %k 10000" +ATTRS{bDeviceClass}!="09", ATTRS{speed}=="10000", RUN+="/usr/bin/udev-usb-sync %k %s{speed}", GOTO="usb_limit_write_cache_end" +ATTRS{bDeviceClass}!="09", ATTRS{speed}=="5000", RUN+="/usr/bin/udev-usb-sync %k %s{speed}", GOTO="usb_limit_write_cache_end" +ATTRS{bDeviceClass}!="09", ATTRS{speed}=="480", RUN+="/usr/bin/udev-usb-sync %k %s{speed}", GOTO="usb_limit_write_cache_end" +ATTRS{bDeviceClass}!="09", ATTRS{speed}=="12", RUN+="/usr/bin/udev-usb-sync %k %s{speed}", GOTO="usb_limit_write_cache_end" + +LABEL="usb_limit_write_cache_end" diff --git a/PKGBUILD b/PKGBUILD index 28bb441..104c6f8 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,18 +1,18 @@ # Maintainer: root.nix.dk pkgname='udev-usb-sync' -pkgver=0.8 -pkgrel=2 +pkgver=0.9 +pkgrel=1 pkgdesc='Fine tune write cache and impose buffer limites when USB storage device is plugged' arch=('any') url='https://codeberg.org/wonky/udev-usb-sync' license=('MIT') -depends=('hdparm') +depends=('hdparm' 'bc') backup=("etc/${pkgname}/${pkgname}.conf") install="${pkgname}.install" source=('99-usb-sync.rules' 'udev-usb-sync' 'udev-usb-sync.conf') -sha256sums=('0c945450f8b472995c27ac4d0b41f333a49a7c8a181827cd57bb80e71194a6f3' - 'b514e3bf1ea55f5e1dc4f5af46da3b5f9f2409da1efe7b36a11647704faf0a8f' - '7cf194b2e3767f8ce4dcbf98b665e46d67624034d5ec0f4cb89f359b677c3687') +sha256sums=('14ff9fa9783f72cb321792ea8a44051d0eb0aaf244edec773d7fa16fdf8dc023' + 'bdc35135e6f8074890a911a501ca4fb3e6a7888963b51c3a1edb98c23bb62ec2' + 'ec26baede73e94f9cfab77cd5aa6e0ffebcc413ff657a4e98eae6c9e2145655e') package() { install -d -m755 "$pkgdir/etc/udev/rules.d" diff --git a/udev-usb-sync b/udev-usb-sync index 1192dcb..46a1df2 100755 --- a/udev-usb-sync +++ b/udev-usb-sync @@ -18,7 +18,7 @@ # @linux-aarhus - root.nix.dk # # configuration : /etc/usb-dev-sync/usb-dev-sync.conf -# triggered by : /usr/lib/udev/rules.d/99-usb-sync.rules +# triggered by : /etc/udev/rules.d/99-usb-sync.rules # # contributors: @megavolt (Manjaro Forum) # : @linux-aarhus (Manjaro Forum) @@ -28,46 +28,51 @@ # $1: usb block device # $2: usb bandwidth reported by device # -# default values (override in configuration file) -# -# block device is passed in $1 -# speed is passed as $2 +set -euo pipefail -# defaults -use_tweaks=1 -use_bandwith=1 -max_ratio=50 -strict_limit=1 -max_bytes=16777216 -# speed defined values -max_bytes_12=10485 -max_bytes_480=629145 -max_bytes_5000=655369 -max_bytes_10000=13107200 +LANG=C +LC_NUMERIC=C -# source configuratoin to override default values -source /etc/udev-usb-sync/udev-usb-sync.conf -if [[ "$use_tweaks" = 0 ]]; then - exit 0 -fi +AUTOCALC=${AUTOCALC:-1} +CONFIG='/etc/udev-usb-sync/udev-usb-sync.conf' -if [[ -z "$1" ]]; then - exit 1 -fi +[[ -f $CONFIG ]] && source $CONFIG -# if speed value is not present use default max_bytes -[[ -z $2 ]] && use_bandwith=0 +BLOCKDEVICE="$1" +SPEED="$2" +KERNEL_MAJOR_VERSION=$(uname -r | awk -F'.' '{print $1}') -# apply max_ratio -echo "$max_ratio" > "/sys/block/$1/bdi/max_ratio" -# apply strict limit -echo "$strict_limit" > "/sys/block/$1/bdi/strict_limit" -# apply max_bytes depending on speed value -if [[ use_bandwith == 0 ]]; then - # apply default value - echo "$max_bytes" > "/sys/block/$1/bdi/max_bytes" -else - # apply bandwidth defined value - echo "$max_bytes_$2" > "/sys/block/%1/bdi/max_bytes" +# disable write cache for device if possible +[[ -n $(which hdparm) ]] && $(which hdparm) -W 0 /dev/$BLOCKDEVICE + +if [[ $KERNEL_MAJOR_VERSION -le 5 ]]; then + # the following rules is introduced with kernel 2.6 + # https://docs.kernel.org/admin-guide/abi-testing.html#abi-sys-class-bdi-bdi-max-ratio + + # 1% of available RAM -> 8046522kB -> 80.465kB -> 80MB + echo 1 > /sys/block/$BLOCKDEVICE/bdi/max_ratio +elif [[ $KERNEL_MAJOR_VERSION -ge 6 ]]; then + # the following rules is introduced with kernel 6.1 + # https://docs.kernel.org/admin-guide/abi-testing.html#abi-sys-class-bdi-bdi-strict-limit + # https://docs.kernel.org/admin-guide/abi-testing.html#abi-sys-class-bdi-bdi-max-bytes + + # apply strict limit + echo 1 > /sys/block/$BLOCKDEVICE/bdi/strict_limit + + if [[ ${AUTOCALC} == 0 ]]; then + # apply 16M as max_bytes + echo 16777216 > /sys/block/$BLOCKDEVICE/bdi/max_bytes + elif [[ ${AUTOCALC} == 1 ]]; then + BUFFER_TIME=${BUFFER_TIME:-"0.05"} + SAFETY_FACTOR=${SAFETY_FACTOR:-"1.3"} + BUFFER_SIZE=$(printf '%.0f' `echo "( ($SPEED / 8) * $BUFFER_TIME * $SAFETY_FACTOR) * 1024 * 1024" | bc`) + # for x in 12 480 5000 10000; do echo -n "$x -> " ;printf "%.0f\n" ` echo "(($x / 8) * 0.05 * 1.3) * 1024 * 1024" | bc`; done + # 62915 + # 4089446 + # 42593157 + # 85196800 + # apply calculated buffer size + echo "$BUFFER_SIZE" > /sys/block/$BLOCKDEVICE/bdi/max_bytes + fi fi \ No newline at end of file diff --git a/udev-usb-sync.conf b/udev-usb-sync.conf index 5e98857..ee3beab 100644 --- a/udev-usb-sync.conf +++ b/udev-usb-sync.conf @@ -24,8 +24,8 @@ # # @linux-aarhus - root.nix.dk # -# configuration : /etc/usb-dev-sync/usb-dev-sync.conf -# triggered by : /usr/lib/udev/rules.d/99-usb-sync.rules +# trigger script: /usr/bin/usb-dev-sync +# triggered by : /etc/udev/rules.d/99-usb-sync.rules # # contributors: @megavolt (Manjaro Forum) # : @linux-aarhus (Manjaro Forum) @@ -33,21 +33,13 @@ # # The values used can be modified if you need to do so # The commented default usually works well -#use_tweaks=1 -#use_bandwith=1 +# +# +## Let it calculate based on given bandwidth +#AUTOCALC=1 -#max_ratio=50 -# strict limit requires kernel >= 6.2 -#strict_limit=1 +## The time in seconds to hold data in RAM +#BUFFER_TIME='0.05' -# a sane default bandwidth value -#max_bytes=16777216 - -# bandwith based limitation requires >= 6.1 -# values as reported by the device ATTRS{speed} -# These values seem to be good and stable. -# It buffers 0,01s of the current bandwidth. -#max_bytes_12=10485 -#max_bytes_480=629145 -#max_bytes_5000=655369 -#max_bytes_10000=13107200 +## multiplicator for safety reasons. +#SAFETY_FACTOR='1.3'