From nobody Fri Jan 13 20:59:39 2023 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 4Ntv1S2l6Mz2pC3H; Fri, 13 Jan 2023 20:59:40 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Ntv1S29snz3tGL; Fri, 13 Jan 2023 20:59:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1673643580; 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=AeEdJsr173GbadBZto7ccMKp2AAmz1cBApluFXlJW8w=; b=QYwlivjoxRxuH8P83hbrIAAUYBpnqd+g3d4gS167IgPKbgKav+40RH1SdFQRQ5GtSrjxhh Nduxit+WJeXh9I3tgT0uudehXK3X8Pn0nGchtP6UfJ5FYQ/X4wZWhxBslmU3CMQFMTpAKw 2wj+YFzWrASR1t0ZO1CFGNzdPWmkV5TsW54f9HlOic1VzNX00aHR4KNAwLd2XKQK/JA2lw 5vrBHzsImvEF9KfQI4qj+3fTd2WWzXwMJg7RuMQrzlUD4867hZh0h34PuViXYHfREcZpp2 seFPlGn/gSJcrCkA5uM1nEiowi2GtjPLfybPJFOwVPEh66LCp95GqsEnqdJxkw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1673643580; 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=AeEdJsr173GbadBZto7ccMKp2AAmz1cBApluFXlJW8w=; b=Sqc5lOaxZeIvAUg2NuiVsECB8Z2o7zbYHBaUjgQfANo0o9dqIpPs6AcatBazBp+ysQJ6fx rHFLF4MXTVTW0daZAc06Bvy4dJjJI5tPHSbIsZdfVjPskHbSR0P1VQYs+KQwBgTSHpJHyn F1GZ1ezgpfVpqKp5/EgrkRxqjaob6I76Ck0My85p1kE2Efc9aVdZwn6A0GKCari3490HkR LpWoKvjDqK6saPEcp1MFZwRzLOjNsJfXOJqB7QxmTjQ9HHCTlHqm+HXPWNU5Cop0AGl8Iv FvJTZm2eLacl+wqBYoVss2fAyjDAylKYs2z1zvrq03CNIVMEjto1hVlz+l+oRA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1673643580; a=rsa-sha256; cv=none; b=JAwTnHEUVNDF5TwZCSTJBnuWOit8O5G9SrZfk/h5uh1M2xSmVYn+eheohMkLwqC/IokxPR qsNqjMW/ekNeMIfDChcsbjtn/8enSYe9Bmpu0sAAc7NbkbAUJRKXN7EyZtBPD+ToD98nke 6Nehj2E5e+JenhQc+SdA4o2V0dR5TvcDZiyCFocu9iLEMvrdK1gQ8BXANoG1MQcBM2BwIa g9AvnKvnGtHivkninIQVQgSVE3L767Fz+ttwMTAlvsuYQJi7EPKBLyvztBi9lCLZsmyOtt DQKp5IT4Y3JShUCuFh3RzCSgHOiDkROO9J13xR+bXz2QR09cmg1HE0pl5agOww== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Ntv1S0fxvzMWn; Fri, 13 Jan 2023 20:59:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 30DKxdQs097051; Fri, 13 Jan 2023 20:59:39 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 30DKxdF7097050; Fri, 13 Jan 2023 20:59:39 GMT (envelope-from git) Date: Fri, 13 Jan 2023 20:59:39 GMT Message-Id: <202301132059.30DKxdF7097050@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mike Karels Subject: git: d6ee3d22f5c4 - stable/13 - growfs script: add swap partition as well as growing root 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: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: karels X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: d6ee3d22f5c477902e79358ff96fefaee6d285d0 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by karels: URL: https://cgit.FreeBSD.org/src/commit/?id=d6ee3d22f5c477902e79358ff96fefaee6d285d0 commit d6ee3d22f5c477902e79358ff96fefaee6d285d0 Author: Mike Karels AuthorDate: 2022-12-10 19:38:36 +0000 Commit: Mike Karels CommitDate: 2023-01-13 19:14:47 +0000 growfs script: add swap partition as well as growing root Add the ability to create a swap partition in the course of growing the root file system on first boot, enabling by default. The default rules are: add swap if the disk is at least 15 GB (decimal), and the existing root is less than 40% of the disk. The default size is 10% of the disk, but is limited by the memory size. The limit is twice memory size up to 4 GB, 8 GB up to 8 GB memory, and memory size over 8 GB memory. Swap size is clamped at vm.swap_maxpages/2 as well. The new swap partition is labeled as "growfs_swap". The default behavior can be overridden by setting growfs_swap_size in /etc/rc.conf or in the kernel environment, with kenv taking priority. A value of 0 inhibits the addition of swap, an empty value specifies the default, and other values indicate a swap size in bytes. By default, addition of swap is inhibited if a swap partition is found in the output of the sysctl kern.geom.conftxt before the current root partition, usually meaning that there is another disk present. Swap space is not added if one is already present in /etc/fstab. The root partition is read-only when growfs runs, so /etc/fstab can not be modified. That step is handled by a new growfs_fstab script, added in a separate commit. Set the value "growfs_swap_pdev" in kenv to indicate that this should be done, as well as for internal use. There is optional verbose output meant for debugging; it can only be enabled by modifying the script (in two places, for sh and awk). This should be removed before release, after testing on -current. Discussed with: cperciva Reviewed by: imp (previous version) Differential Revision: https://reviews.freebsd.org/D37462 (cherry picked from commit 4a30d7bb373c08f42f953b9cd1e793e236b4cd92) --- libexec/rc/rc.d/growfs | 178 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 172 insertions(+), 6 deletions(-) diff --git a/libexec/rc/rc.d/growfs b/libexec/rc/rc.d/growfs index 5402bd442279..3c48a7dca6b2 100755 --- a/libexec/rc/rc.d/growfs +++ b/libexec/rc/rc.d/growfs @@ -1,5 +1,6 @@ #!/bin/sh # +# Copyright 2022 Michael J. Karels # Copyright 2014 John-Mark Gurney # All rights reserved. # @@ -32,8 +33,9 @@ # BEFORE: root # KEYWORD: firstboot -# This allows us to distribute an image -# and have it work on essentially any size drive. +# Grow root partition to fill available space, optionally adding a swap +# partition at the end. This allows us to distribute an image and +# have it work on essentially any size drive. # Note that this uses awk(1), and thus will not work if /usr is on a separate # filesystem. We need to run early, because there might be not enough free @@ -48,7 +50,7 @@ start_cmd="growfs_start" stop_cmd=":" rcvar="growfs_enable" -growfs_get_diskdev () +growfs_get_diskdev() { local _search=${1} sysctl -b kern.geom.conftxt | @@ -61,8 +63,51 @@ growfs_get_diskdev () done } -growfs_start () +# Compute upper bound on swap partition size (if added), based on physmem +# and vm.swap_maxpages / 2 (the limit that elicits a warning). +# Rule for swap size based on memory size: +# up to 4 GB twice memory size +# 4 GB - 8 GB 8 GB +# over 8 GB memory size +growfs_swap_max() { + memsize=$(sysctl -n hw.physmem) + memsizeMB=$(($memsize / (1024 * 1024))) + + if [ $memsizeMB -lt 4096 ] + then + swapmax=$(($memsize * 2)) + elif [ $memsizeMB -lt 8192 ] + then + swapmax=$((8192 * 1024 * 1024)) + else + swapmax=$memsize + fi + + pagesize=$(sysctl -n hw.pagesize) + vm_swap_max=$(($(sysctl -n vm.swap_maxpages) / 2 * $pagesize)) + + if [ $swapmax -gt $vm_swap_max ] + then + $swapmax=$vm_swap_max + fi + echo -n "$swapmax" +} + +# Find newly-added swap partition on parent device ($1). +growfs_last_swap() +{ + swapdev=$(gpart list $1 | awk ' + $2 == "Name:" { dev = $3 } + $1 == "type:" && $2 == "freebsd-swap" { swapdev = dev } + END { print swapdev } + ') + echo -n $swapdev +} + +growfs_start() +{ + verbose=0 echo "Growing root partition to fill device" FSTYPE=$(mount -p | awk '{ if ( $2 == "/") { print $3 }}') FSDEV=$(mount -p | awk '{ if ( $2 == "/") { print $1 }}') @@ -100,19 +145,126 @@ growfs_start () diskdev=${rootdev} fi + # Check kenv for growfs_swap_size; if not present, + # check $growfs_swap_size from /etc/rc.conf. + # A value of 0 suppresses swap addition, + # "" (or unset) specifies the default; + # other values indicate the size in bytes. + # If default, check whether swap is already in fstab; + # if so, don't add another. + addswap=1 + swapsize="$(kenv -q growfs_swap_size 2>/dev/null)" + case "$swapsize" in + "0") addswap=0 + ;; + "") case "$growfs_swap_size" in + "0") addswap=0 + ;; + "") + if ! awk ' + /^#/ { next } + $3 == "swap" { exit 1 } + ' < /etc/fstab + then + addswap=0 + fi + ;; + *) swapsize="$growfs_swap_size" + ;; + esac + ;; + *) ;; + esac + + swaplim=$(growfs_swap_max) + + [ $verbose -eq 1 ] && { + echo "diskdev is $diskdev" + echo "search is $search" + echo "swapsize is $swapsize" + echo "swaplim is $swaplim" + } + sysctl -b kern.geom.conftxt | awk ' { + verbose = 0 lvl=$1 device[lvl] = $3 type[lvl] = $2 idx[lvl] = $7 + offset[lvl] = $9 parttype[lvl] = $13 + size[lvl] = $4 + if (verbose) print lvl, type[lvl], $3 + if (type[lvl] == "DISK") { + disksize = size[lvl] + if (verbose) + print "disksize ", disksize + # Don't add swap on disks under 15 GB (decimal) by default. + if (addswap == 1 && (size[lvl] > 15000000000 || swapsize > 0)) + doing_swap = 1 + else + doing_swap = 0 + } else if (type[lvl] == "PART" && $11 == "freebsd-swap" && \ + int(swapsize) == 0) { + # This finds swap only if it precedes root, e.g. preceding disk. + addswap = 0 + doing_swap = 0 + print "swap device exists, not adding swap" + } if (dev == $3) { for (i = 1; i <= lvl; i++) { # resize if (type[i] == "PART") { pdev = device[i - 1] - cmd[i] = "gpart resize -i " idx[i] " " pdev + if (verbose) + print i, pdev, addswap, disksize, \ + doing_swap + swapcmd = "" + # Allow swap if current root is < 40% of disk. + if (parttype[i] != "MBR" && doing_swap == 1 && \ + (size[i] / disksize < 0.4 || \ + swapsize > 0)) { + print "Adding swap partition" + if (int(swapsize) == 0) { + swapsize = int(disksize / 10) + if (swapsize > swaplim) + swapsize = swaplim + } + sector = $5 + swapsize /= sector + if (verbose) + print "swapsize sectors", + swapsize + align = 4 * 1024 * 1024 / sector + + # Estimate offset for swap; let + # gpart compute actual start and size. + # Assume expansion all goes into this + # partition for MBR case. + if (parttype[i - 1] == "MBR") { + if (verbose) + print "sz ", size[i - 1], \ + " off ", offset[i - 1] + expand = size[0] - \ + (size[i - 1] + offset[i - 1]) + } else { + if (verbose) + print "sz ", size[i], \ + " off ", offset[i] + expand = size[0] - \ + (size[i] + offset[i]) + } + if (verbose) + print "expand ", expand, \ + " sz ", size[i] + swapbase = (expand + size[i]) / sector + swapbase -= swapsize + align + swapcmd = "gpart add -t freebsd-swap -a " align " -b " swapbase " " pdev "; kenv growfs_swap_pdev=" pdev " >/dev/null; " + if (verbose) + swapcmd = "set -x; " swapcmd + } + cmd[i] = swapcmd "gpart resize -i " idx[i] " " pdev if (parttype[i] == "GPT") cmd[i] = "gpart recover " pdev " ; " cmd[i] } else if (type[i] == "LABEL") { @@ -128,7 +280,7 @@ growfs_start () } exit 0 } -}' dev="$search" +}' dev="$search" addswap="$addswap" swapsize="$swapsize" swaplim="$swaplim" gpart commit "$diskdev" 2> /dev/null case "$FSTYPE" in ufs) @@ -138,6 +290,20 @@ growfs_start () zpool online -e $pool $rootdev ;; esac + + # Get parent device of swap partition if one was added; + # if so, find swap device and label it. + pdev=$(kenv -q growfs_swap_pdev) + if [ -n "$pdev" ] + then + dev=$(growfs_last_swap "$pdev") + if [ -z "$dev" ] + then + echo "Swap partition not found on $pdev" + exit 0 + fi + glabel label -v growfs_swap $dev + fi } load_rc_config $name