From nobody Tue Sep 15 22:50:24 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hky0K28QDz6rhnv for ; Tue, 15 Sep 2026 22:50:25 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hky0J5xxdz4bmR for ; Tue, 15 Sep 2026 22:50:24 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789512624; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=v7ZhwxoLO4cNa1oQanePMN8UUlk9QpwrpGOFvPpyYss=; b=AlUTTmvSc7II90kxECpikWh2L4zbPxadqT/Wm2pUV2nKJl8jHIVMVxNqCr4dcetSMvO3Pq dS8Wiz6MmWmHD7aIKF0Pi5niG2h4ivW71WeJMpWcr1almSNAgZ2tJJKxCDrkZ2HUy5WumL qWPLSs54dpXfi66FjhSpDhA/8r0la6q03gvT5Gantyt6c9duWyEa6S6MHKx80g3n30d78L PjVoCK8DrUQyHY6XODLWfNo2RL2le9Q6QVKnrf1SXnO+tZd/TdPtrHOj6uQzh8tol2IuAw jVxgl6uUNMDJha0rFHaPzaud9c9+mpjX09K1teclgc9pMSF3qN90MGmx77lGNA== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789512624; b=APxu0ONU8tH7+58qYiwxSdNIe1umtWizB56zWRJbGx0a1Oy/2tTBjHJZLSm4sbiIQC3ha3 Rw7PlTdg31iFGpLN29G+dcYBWbfr1keEwebTJa20Ax99soDw+lUyXS0+9ilFX5hRp+xmS0 Zvp7dM/K6Mc4tu6deqkh/ExxyltPU12Ls0lSlNqDc9kORmqgoOeM6cM1iOmEzNKz5Ro2dk KUg/KyGMYpG1YB+1PMWNkCQ/04ahmyuAlPOehLathyizyF4wJSucLAdufqmXa+fj4ZOQeB qFXceMGEb613woS0yzT+l84fxX3v3Fpqg3NLvYv9Yutt1kY50tVY+MJ/ReBQ+A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789512624; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=v7ZhwxoLO4cNa1oQanePMN8UUlk9QpwrpGOFvPpyYss=; b=IpxJ+VvvCgPZuaN7l5r6WSBpfstIyW97HbhXT453jK1H3cSp4q9bq24wzroiMCLdnTWwh8 7+GBbCdS+ovQTqe8SsuL5++IzHtfBEZwr956HZ6T64h1ziLEaCzAg1xNoxgGR5Yl5XldsE 7TjlP3+WGh2HHUNJNPPZHoU5u4t+UtEN9nPMKB3nn5Vs9CPaeWIrko2mMetR63UGcutkTc 6LW84VOzlEYaIgGqNcC9fGdZIJDzYPhijXYfLhot3qwA0ZbwYaXZWphQw1g38vymBpE/29 2u6qQ/sJJlwCivgE8jotKM8Y61gD8sSoH8US3o1KVxbVQqufLa1m8LAQ72iChg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hky0J3rDnzJW2 for ; Tue, 15 Sep 2026 22:50:24 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1d280 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 15 Sep 2026 22:50:24 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Colin Percival Subject: git: ba004afc874b - stable/15 - rc+devd: Add growfs_postboot List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: cperciva X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: ba004afc874bb805410c292455a5ce3a32a7954d Auto-Submitted: auto-generated Date: Tue, 15 Sep 2026 22:50:24 +0000 Message-Id: <6aa9cbb0.1d280.52cd8d21@gitrepo.freebsd.org> The branch stable/15 has been updated by cperciva: URL: https://cgit.FreeBSD.org/src/commit/?id=ba004afc874bb805410c292455a5ce3a32a7954d commit ba004afc874bb805410c292455a5ce3a32a7954d Author: Colin Percival AuthorDate: 2026-07-30 20:20:51 +0000 Commit: Colin Percival CommitDate: 2026-09-15 22:49:42 +0000 rc+devd: Add growfs_postboot In VM and cloud environments it is often possible to enlarge virtual disks; this can be useful, for example, if a system is launched with a small root disk and it later becomes clear that more space is needed. On kernels which support run-time resizing of disks (for NVMe, this was added in November 2025; some other disk types have supported this for longer) a SIZECHANGE notification is sent to userland via devd. Add a "nostart" rc.d script (runnable manually but not automatically at boot time) and a devd script which invokes it when a notification arrives. The rc.d script enlarges the "final partition" on partitioned geoms, or the UFS filesystem or zpool device when triggered on a disk containing either of those. Reviewed by: imp, ziaee MFC after: 2 weeks Relnotes: Disk partitions and filesystems can be enlarged automatically when disks grow by setting growfs_postboot_enable=YES in /etc/rc.conf. Sponsored by: Amazon Differential Revision: https://reviews.freebsd.org/D58582 (cherry picked from commit 5a31987d4c395ec4d3ed303cbc2e1d12ea54a039) --- libexec/rc/rc.conf | 3 + libexec/rc/rc.d/Makefile | 1 + libexec/rc/rc.d/growfs_postboot | 116 +++++++++++++++++++++++++++++++++++++++ sbin/devd/Makefile | 1 + sbin/devd/growfs_postboot.conf | 8 +++ share/man/man5/rc.conf.5 | 1 + share/man/man7/Makefile | 1 + share/man/man7/growfs.7 | 1 + share/man/man7/growfs_postboot.7 | 69 +++++++++++++++++++++++ 9 files changed, 201 insertions(+) diff --git a/libexec/rc/rc.conf b/libexec/rc/rc.conf index 11ec74b93a23..d84922beb17d 100644 --- a/libexec/rc/rc.conf +++ b/libexec/rc/rc.conf @@ -122,6 +122,9 @@ background_fsck_delay="60" # Time to wait (seconds) before starting the fsck. growfs_enable="NO" # Set to YES to attempt to grow the root filesystem on boot growfs_swap_size="" # Set to 0 to disable growfs swap, "" to default size, # size in bytes to specify swap size. +growfs_postboot_enable="NO" # Set to YES to attempt to grow partitions and + # filesystems when devd notifies about disks growing + # after the system boots. netfs_types="nfs:NFS smbfs:SMB" # Net filesystems. extra_netfs_types="NO" # List of network extra filesystem types for delayed # mount at startup (or NO). diff --git a/libexec/rc/rc.d/Makefile b/libexec/rc/rc.d/Makefile index cb94380aff32..f6646208dc03 100644 --- a/libexec/rc/rc.d/Makefile +++ b/libexec/rc/rc.d/Makefile @@ -24,6 +24,7 @@ CONFS= DAEMON \ fsck \ growfs \ growfs_fstab \ + growfs_postboot \ hostid \ hostid_save \ hostname \ diff --git a/libexec/rc/rc.d/growfs_postboot b/libexec/rc/rc.d/growfs_postboot new file mode 100755 index 000000000000..346c8a0d7162 --- /dev/null +++ b/libexec/rc/rc.d/growfs_postboot @@ -0,0 +1,116 @@ +#!/bin/sh +# +# Copyright 2026 Colin Percival +# +# SPDX-License-Identifier: BSD-2-Clause +# +# PROVIDE: growfs_postboot +# KEYWORD: nostart + +# Triggered by /etc/devd/growfs_postboot.conf: When a disk grows, enlarge the +# final partition to fill the available space (if the disk is partitioned) or +# enlarge the UFS filesystem or ZFS zpool (if in use for one of those). Note +# that in the common case of "a disk is partitioned and one of the partitions +# contains a filesystem" this script is invoked twice -- the repartitioning +# done on the first call generates a new devd event which triggers the second +# invocation. +# +# Enable by setting +# growfs_postboot_enable=YES +# in /etc/rc.conf. Note that on systems with growfs_enable=YES, it will often +# be necessary to set growfs_swap_size=0 in order to disable swap creation; +# otherwise the "final partition" is the swap space, not the filesystem and +# growing the disk will not cause the most likely desired results. + +. /etc/rc.subr + +name="growfs_postboot" +desc="automatically grow file systems during runtime" +rcvar="growfs_postboot_enable" +start_cmd="growfs_postboot_start" + +disktype() { + sysctl -n kern.geom.conftxt | awk -v dev="$1" ' + BEGIN { + partitioned=0 + indev=0 + } + { + if (dev == $3) { + indev=1 + devlevel=$1 + } else if (devlevel >= $1) { + indev=0 + } else if (indev == 1) { + if ($2 == "PART") { + partitioned=1 + } + } + } + END { + if (partitioned == 1) { + print "partitioned" + } else { + print "unpartitioned" + } + }' +} + +growpart() { + # Run 'gpart recover' if GPT + if gpart list "$1" | grep -qi 'scheme: GPT'; then + gpart recover "$1" || true + fi + + # Find the index of the last partition; note that we need to compare + # the starting sectors in case partitions are not numbered sensibly. + idx=$(gpart backup "$1" | awk ' + NR == 1 { next } + $3 + 0 > start { start = $3 + 0; idx = $1 } + END { print idx }') + if [ -z "$idx" ]; then + echo "Error finding final partition of $1" + return 1 + fi + + # Expand that partition + gpart resize -i "$idx" "$1" +} + +growfilesystem() { + case $(fstyp -u "/dev/$1" 2>/dev/null) in + ufs) growfs -y "/dev/$1" + ;; + zfs) zpool list -H -o name | + while read -r pool; do + zpool list -vH -o name "$pool" | + grep "^[[:space:]]" | + while read -r dev; do + if [ "$dev" = "$1" ]; then + zpool online -e "$pool" "$1" + fi + done + done + ;; + "") # Nothing to grow here + ;; + *) echo "Don't know how to grow filesystem on /dev/$1" + ;; + esac +} + +growfs_postboot_start() { + # Run either growpart or growfilesystem depending on whether this is + # something which is partitioned or not. + case $(disktype "$1") in + partitioned) + growpart "$1" + ;; + unpartitioned) + growfilesystem "$1" + ;; + esac +} + +load_rc_config $name +run_rc_command "$@" diff --git a/sbin/devd/Makefile b/sbin/devd/Makefile index 78b2b039ac6e..864df3604d64 100644 --- a/sbin/devd/Makefile +++ b/sbin/devd/Makefile @@ -5,6 +5,7 @@ PACKAGE=devd CONFGROUPS= CONFS DEVD CONFS= devd.conf DEVD= devmatch.conf +DEVD+= growfs_postboot.conf DEVDDIR= /etc/devd .if ${MK_ACPI} != "no" DEVD+= asus.conf diff --git a/sbin/devd/growfs_postboot.conf b/sbin/devd/growfs_postboot.conf new file mode 100644 index 000000000000..0c6b817755ec --- /dev/null +++ b/sbin/devd/growfs_postboot.conf @@ -0,0 +1,8 @@ +# Trigger growfs on GEOM size changes. + +notify 200 { + match "system" "GEOM"; + match "subsystem" "DEV"; + match "type" "SIZECHANGE"; + action "lockf -k /var/run/growfs_postboot.lock /etc/rc.d/growfs_postboot quietstart $cdev 2>&1 | logger -t growfs_postboot &"; +}; diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index 5e02d1f199cc..586e33980fd8 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -5171,6 +5171,7 @@ to .Xr pf.conf 5 , .Xr firewall 7 , .Xr growfs 7 , +.Xr growfs_postboot 7 , .Xr security 7 , .Xr tuning 7 , .Xr accton 8 , diff --git a/share/man/man7/Makefile b/share/man/man7/Makefile index 6fd32da900e1..ba2633840ab0 100644 --- a/share/man/man7/Makefile +++ b/share/man/man7/Makefile @@ -16,6 +16,7 @@ MAN= arch.7 \ firewall.7 \ groups.7 \ growfs.7 \ + growfs_postboot.7 \ hier.7 \ hostname.7 \ intro.7 \ diff --git a/share/man/man7/growfs.7 b/share/man/man7/growfs.7 index 43648d8d9f2b..6b026570ceee 100644 --- a/share/man/man7/growfs.7 +++ b/share/man/man7/growfs.7 @@ -124,6 +124,7 @@ must be available prior to running the script. .Sh SEE ALSO .Xr fstab 5 , .Xr rc.conf 5 , +.Xr growfs_postboot 7 , .Xr growfs 8 , .Xr zpool 8 .Sh HISTORY diff --git a/share/man/man7/growfs_postboot.7 b/share/man/man7/growfs_postboot.7 new file mode 100644 index 000000000000..147934744edf --- /dev/null +++ b/share/man/man7/growfs_postboot.7 @@ -0,0 +1,69 @@ +.\" +.\" Copyright 2026 Colin Percival +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd July 31, 2026 +.Dt GROWFS_POSTBOOT 7 +.Os +.Sh NAME +.Nm growfs_postboot +.Nd automatically grow file systems during runtime +.Sh DESCRIPTION +The +.Nm +script expands filesystems automatically. +Typically it is run via +.Xr devd 8 +in response to a SIZECHANGE notification. +It will enlarge the final partition of a partitioned disk; expand a UFS +file system; or expand a zpool device, as appropriate. +.Pp +The following option in +.Pa /etc/rc.conf +controls the behavior of +.Nm : +.Bl -tag -width "growfs_postboot_enable" -offset indent +.It Va growfs_postboot_enable +.Pq Dq Li NO +If set to +.Dq Li YES , +the script will enlarge partitions and file systems when disks expand. +.El +.Pp +Note that the +.Xr growfs 7 +startup script will normally place a swap partition at the end of the disk +containing the root file system, which will prevent the file system growing +further; as such, in most cases it will be advisable to set +.Va growfs_swap_size +to +.Dq Li 0 +in virtual machine images if +.Nm +is being enabled. +If the system has already booted without that setting, a swap partition may +have already been created, in which case it must be removed before this script +can grow the root file system. +.Sh FILES +.Bl -tag -compact -width Pa +.It Pa /etc/rc.conf +.El +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr rc.conf 5 , +.Xr growfs 7 , +.Xr devd 8 , +.Xr growfs 8 , +.Xr zpool 8 +.Sh HISTORY +The +.Nm +script first appeared in +.Fx 16.0 . +.Sh AUTHORS +.An Colin Percival Aq Mt cperciva@FreeBSD.org +.Sh CAVEATS +I/O may be paused while file systems grow, so this functionality should be used +with care on systems with strict latency requirements.