From a177877ce379c469255870bcb75664bc56d408a7 Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Fri, 24 Apr 2026 23:48:22 -0400 Subject: [PATCH] zfs: add test fix for deadlock --- modules/zfs.nix | 9 ++++- .../zfs/0001-remove-dbuf_evict_one-call.patch | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 patches/zfs/0001-remove-dbuf_evict_one-call.patch diff --git a/modules/zfs.nix b/modules/zfs.nix index 4e5da01..4ed5e9b 100644 --- a/modules/zfs.nix +++ b/modules/zfs.nix @@ -20,7 +20,14 @@ let arcMaxBytes = (totalRamBytes - totalHugepageBytes) * 60 / 100; in { - boot.zfs.package = pkgs.zfs_2_4; + # remove inline dbuf_evict_one call so the dedicated eviction thread + # handles cache pressure instead of stalling txg_sync on 6.14+. + # https://github.com/openzfs/zfs/issues/18426 + boot.zfs.package = pkgs.zfs_2_4.overrideAttrs (old: { + patches = (old.patches or [ ]) ++ [ + ../patches/zfs/0001-remove-dbuf_evict_one-call.patch + ]; + }); boot.initrd.kernelModules = [ "zfs" ]; boot.kernelParams = [ diff --git a/patches/zfs/0001-remove-dbuf_evict_one-call.patch b/patches/zfs/0001-remove-dbuf_evict_one-call.patch new file mode 100644 index 0000000..01ce312 --- /dev/null +++ b/patches/zfs/0001-remove-dbuf_evict_one-call.patch @@ -0,0 +1,34 @@ +--- a/module/zfs/dbuf.c 2026-04-24 14:20:12.565390796 -0400 ++++ b/module/zfs/dbuf.c 2026-04-24 14:20:40.711198653 -0400 +@@ -864,23 +864,16 @@ + dbuf_evict_notify(uint64_t size) + { + /* +- * We check if we should evict without holding the dbuf_evict_lock, +- * because it's OK to occasionally make the wrong decision here, +- * and grabbing the lock results in massive lock contention. ++ * Wake the dedicated eviction thread when the cache ++ * exceeds target. Inline eviction from write-completion ++ * context is intentionally avoided: it adds a second ++ * multilist sublist lock to every write, and when ++ * kmem_cache_free is slow (__free_frozen_pages zone lock ++ * contention on 6.14+), the cascade stalls txg_sync. ++ * See openzfs#18426. + */ +- if (size > dbuf_cache_target_bytes()) { +- /* +- * Avoid calling dbuf_evict_one() from memory reclaim context +- * (e.g. Linux kswapd, FreeBSD pagedaemon) to prevent deadlocks. +- * Memory reclaim threads can get stuck waiting for the dbuf +- * hash lock. +- */ +- if (size > dbuf_cache_hiwater_bytes() && +- !current_is_reclaim_thread()) { +- dbuf_evict_one(); +- } ++ if (size > dbuf_cache_target_bytes()) + cv_signal(&dbuf_evict_cv); +- } + } + + /*