Linux system udev rule to disable write-cache for USB storage
Go to file
Grumpy Coder 0287d33018 Update 2023-10-16 04:40:01 +00:00
.gitignore Initial commit 2023-03-05 05:57:39 +00:00
99-usb-sync.rules Update 99-usb-sync.rules 2023-10-16 04:38:27 +00:00
LICENSE Initial commit 2023-03-05 05:57:39 +00:00
PKGBUILD Update PKGBUILD 2023-10-16 04:34:36 +00:00 Update 2023-10-16 04:40:01 +00:00
udev-usb-sync Update udev-usb-sync 2023-08-29 15:48:55 +00:00
udev-usb-sync.conf update with config and script 2023-08-29 16:25:04 +02:00
udev-usb-sync.install update with config and script 2023-08-29 16:25:04 +02:00

Disable write cache for usb storage devices

Manjaro Forum topic

Linux filesystem cache

Linux agressively caches files in order to improve overall performance.

When copying large amount of files to an USB storage this often results in some wait time until the device can be safely removed.

How long you have to wait depends on your system and the quality of the USB storage device.

Numerous issues regarding this has resulted in various suggestions involving sysctl tweaks and trim. udev rule to disable write-cache

udev rule to disable write-cache

In another place one user threw in an udev rule which would disable write-cache for devices when they were added and while it was just an idea - it triggered my curiosity.

I dug into the intricacies of udev and found a method to only target USB storage devices.

The rule has gotten a major overhaul and now consist of the rule, a config file and a script

The rule /etc/udev/rules.d/99-usb-sync.rules

# 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"

# the following rules is introduced with kernel 6.2
ACTION=="add|change", KERNEL=="sd[a-z]", ENV{ID_USB_TYPE}=="disk", RUN+="/usr/bin/udev-usb-sync %k"

The config /etc/usb-dev-sync/udev-usb-sync.conf

# default values 

The script /usr/bin/udev-usb-sync

# script to tweak USB storage device filesystem sync
# sources /etc/usb-dev-sync/usb-dev-sync.conf


# read user config
source /etc/udev-usb-sync/udev-usb-sync.conf

if [[ "$use_tweaks" = 0 ]]; then
        exit 0

if [[ -z "$1" ]]; then
        exit 1

echo "$max_bytes" > "/sys/block/$1/bdi/max_bytes"
echo "$max_ratio" > "/sys/block/$1/bdi/max_ratio"
echo "$strict_limit" > "/sys/block/$1/bdi/strict_limit"

The rule activates when udev detects

  • add or change
  • kernel event for disk devices sd[a-z]
  • only if the device environment ID_USB_TYPE=='disk'
  • run
    • hdparm -W 0 /dev/%k (disable write cache if supported)
    • udev-usb-sync %k
      • applies defaults
      • read config and apply user values
      • if use_tweaks=0 the script exits
      • if use_tweaks=1 the applies the values (default or config)

Create a file in /etc/udev/rules.d/99-usb-sync.rules and paste the rule into it. Create a file in /etc/udev-usb-sync/udev-usb-sync.conf and paste the default values. Create a file in /usr/bin/udev-usb-sync and paste the script content.

Install hdparm package.

sudo pacman -Syu hdparm

Reload udev

sudo udevadm control --reload

Then plug an usb device - open in your file manager - copy a huge amout of files to the device - when the copy is done - click eject in the file manager - note how quick the device is ejected.

For those preferring the package manager, I have created a PKGBUILD which will pull the hdparm dependency upon installation.

pamac build udev-usb-sync

Another idea by @megavolt at Manjaro Forum which does not require hdparm.