git: 493908c4b45c - main - periodic/daily/801.trim-zfs: Add a daily zfs trim script

From: Warner Losh <imp_at_FreeBSD.org>
Date: Tue, 09 Apr 2024 21:57:07 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=493908c4b45c7b75e4a6b4aea3b5b63ea5c268d5

commit 493908c4b45c7b75e4a6b4aea3b5b63ea5c268d5
Author:     Lexi Winter <lexi@le-fay.org>
AuthorDate: 2024-04-09 21:49:56 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-04-09 21:55:11 +0000

    periodic/daily/801.trim-zfs: Add a daily zfs trim script
    
    As mentioned in zpoolprops(7), on some SSDs, it may not be desirable to
    use ZFS autotrim because a large number of trim requests can degrade
    disk performance; instead, the pool should be manually trimmed at
    regular intervals.
    
    Add a new daily periodic script for this purpose, 801.trim-zfs.  If
    enabled (daily_trim_zfs_enable=YES; the default is NO), it will run a
    'zpool trim' operation on all online pools, or on the pools listed in
    'daily_trim_zfs_pools'.
    
    The trim is not started if the pool is degraded (which matches the
    behaviour of the existing 800.scrub-zfs script) or if a trim is already
    running on that pool.  Having autotrim enabled does not inhibit the
    periodic trim; it's sometimes desirable to run periodic trims even with
    autotrim enabled, because autotrim can elide trims for very small
    regions.
    
    PR:             275965
    MFC after:      1 week
    Reviewed by:    imp
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/956
---
 share/man/man5/periodic.conf.5           | 11 +++++-
 usr.sbin/periodic/etc/daily/801.trim-zfs | 59 ++++++++++++++++++++++++++++++++
 usr.sbin/periodic/etc/daily/Makefile     |  3 +-
 usr.sbin/periodic/periodic.conf          |  5 +++
 4 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/share/man/man5/periodic.conf.5 b/share/man/man5/periodic.conf.5
index 29fff146c212..a2ed2b09d772 100644
--- a/share/man/man5/periodic.conf.5
+++ b/share/man/man5/periodic.conf.5
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd December 31, 2023
+.Dd April 9, 2024
 .Dt PERIODIC.CONF 5
 .Os
 .Sh NAME
@@ -634,6 +634,15 @@ The same as
 .Va daily_scrub_zfs_default_threshold
 but specific to the pool
 .Ao Ar poolname Ac Ns .
+.It Va daily_trim_zfs_enable
+.Pq Vt bool
+Set to
+.Dq Li YES
+if you want to run a zfs trim daily.
+.It Va daily_trim_zfs_pools
+.Pq Vt str
+A space separated list of names of zfs pools to trim.
+If the list is empty or not set, all zfs pools are trimmed.
 .It Va daily_local
 .Pq Vt str
 Set to a list of extra scripts that should be run after all other
diff --git a/usr.sbin/periodic/etc/daily/801.trim-zfs b/usr.sbin/periodic/etc/daily/801.trim-zfs
new file mode 100755
index 000000000000..17d2ce217c10
--- /dev/null
+++ b/usr.sbin/periodic/etc/daily/801.trim-zfs
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+#
+
+# If there is a global system configuration file, suck it in.
+#
+
+if [ -r /etc/defaults/periodic.conf ]
+then
+    . /etc/defaults/periodic.conf
+    source_periodic_confs
+fi
+
+case "$daily_trim_zfs_enable" in
+    [Yy][Ee][Ss])
+	echo
+	echo 'Trimming of zfs pools:'
+
+	if [ -z "${daily_trim_zfs_pools}" ]; then
+		daily_trim_zfs_pools="$(zpool list -H -o name)"
+	fi
+
+	rc=0
+	for pool in ${daily_trim_zfs_pools}; do
+		# sanity check
+		_status=$(zpool list -Hohealth "${pool}" 2> /dev/null)
+		if [ $? -ne 0 ]; then
+			rc=2
+			echo "   WARNING: pool '${pool}' specified in"
+			echo "            '/etc/periodic.conf:daily_trim_zfs_pools'"
+			echo "            does not exist"
+			continue
+		fi
+		case ${_status} in
+		FAULTED)
+			rc=3
+			echo "Skipping faulted pool: ${pool}"
+			continue ;;
+		UNAVAIL)
+			rc=4
+			echo "Skipping unavailable pool: ${pool}"
+			continue ;;
+		esac
+
+		if ! zpool status "${pool}" | grep -q '(trimming)'; then
+			echo "    starting trim of pool '${pool}'"
+			zpool trim ${daily_zfs_trim_flags} "${pool}"
+		else
+			echo "    trim of pool '${pool}' already in progress, skipping"
+		fi
+	done
+	;;
+
+    *)
+	rc=0
+	;;
+esac
+
+exit $rc
diff --git a/usr.sbin/periodic/etc/daily/Makefile b/usr.sbin/periodic/etc/daily/Makefile
index 4eabc0bb1d52..3bf4601f5145 100644
--- a/usr.sbin/periodic/etc/daily/Makefile
+++ b/usr.sbin/periodic/etc/daily/Makefile
@@ -60,7 +60,8 @@ SENDMAILPACKAGE=	sendmail
 .if ${MK_ZFS} != "no"
 CONFS+=	223.backup-zfs \
 	404.status-zfs \
-	800.scrub-zfs
+	800.scrub-zfs  \
+	801.trim-zfs
 .endif
 
 .include <bsd.prog.mk>
diff --git a/usr.sbin/periodic/periodic.conf b/usr.sbin/periodic/periodic.conf
index 5e3a7837c6b4..608a199b3cc9 100644
--- a/usr.sbin/periodic/periodic.conf
+++ b/usr.sbin/periodic/periodic.conf
@@ -179,6 +179,11 @@ daily_scrub_zfs_pools=""			# empty string selects all pools
 daily_scrub_zfs_default_threshold="35"		# days between scrubs
 #daily_scrub_zfs_${poolname}_threshold="35"	# pool specific threshold
 
+# 801.trim-zfs
+daily_trim_zfs_enable="NO"
+daily_trim_zfs_pools=""				# empty string selects all pools
+daily_trim_zfs_flags=""				# zpool-trim(8) flags
+
 # 999.local
 daily_local="/etc/daily.local"				# Local scripts