xref: /freebsd/libexec/rc/rc.d/growfs (revision 8e9740b62e950b40dcf7dbe729855be14450d40d)
1#!/bin/sh
2#
3# Copyright 2014 John-Mark Gurney
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26#
27# $FreeBSD$
28#
29
30# PROVIDE: growfs
31# REQUIRE: fsck
32# BEFORE: root
33# KEYWORD: firstboot
34
35# This allows us to distribute an image
36# and have it work on essentially any size drive.
37
38# Note that this uses awk(1), and thus will not work if /usr is on a separate
39# filesystem.  We need to run early, because there might be not enough free
40# space on rootfs for the boot to succeed, and on images we ship - which are
41# the primary purpose of this script - there is no separate /usr anyway.
42
43. /etc/rc.subr
44
45name="growfs"
46desc="Grow root partition to fill device"
47start_cmd="growfs_start"
48stop_cmd=":"
49rcvar="growfs_enable"
50
51growfs_get_diskdev ()
52{
53	local _search=${1}
54	sysctl -b kern.geom.conftxt |
55	while read x1 _type _dev line
56	do
57		if [ "${_type}" = "DISK" -a -n "$(echo ${_search} | grep ${_dev})" ]; then
58			echo -n ${_dev}
59			break
60		fi
61	done
62}
63
64growfs_start ()
65{
66	echo "Growing root partition to fill device"
67	FSTYPE=$(mount -p | awk '{ if ( $2 == "/") { print $3 }}')
68	FSDEV=$(mount -p | awk '{ if ( $2 == "/") { print $1 }}')
69	case "$FSTYPE" in
70	ufs)
71		rootdev=${FSDEV#/dev/}
72		;;
73	zfs)
74		pool=${FSDEV%%/*}
75		rootdev=$(zpool list -v $pool | awk 'END { print $1 }')
76		;;
77	*)
78		echo "Don't know how to grow root filesystem type: $FSTYPE"
79		return
80	esac
81	if [ x"$rootdev" = x"${rootdev%/*}" ]; then
82		# raw device
83		rawdev="$rootdev"
84	else
85		rawdev=$(glabel status | awk -v rootdev=$rootdev 'index(rootdev, $1) { print $3; }')
86		if [ x"$rawdev" = x"" ]; then
87			echo "Can't figure out device for: $rootdev"
88			return
89		fi
90	fi
91
92	if [ x"diskid" = x"${rootdev%/*}" ]; then
93		search=$rootdev
94	else
95		search=$rawdev
96	fi
97
98	diskdev=$(growfs_get_diskdev ${search})
99	if [ -z "${diskdev}" ]; then
100		diskdev=${rootdev}
101	fi
102
103	sysctl -b kern.geom.conftxt | awk '
104{
105	lvl=$1
106	device[lvl] = $3
107	type[lvl] = $2
108	idx[lvl] = $7
109	parttype[lvl] = $13
110	if (dev == $3) {
111		for (i = 1; i <= lvl; i++) {
112			# resize
113			if (type[i] == "PART") {
114				pdev = device[i - 1]
115				cmd[i] = "gpart resize -i " idx[i] " " pdev
116				if (parttype[i] == "GPT")
117					cmd[i] = "gpart recover " pdev " ; " cmd[i]
118			} else if (type[i] == "LABEL") {
119				continue
120			} else {
121				print "unhandled type: " type[i]
122				exit 1
123			}
124		}
125		for (i = 1; i <= lvl; i++) {
126			if (cmd[i])
127				system(cmd[i])
128		}
129		exit 0
130	}
131}' dev="$search"
132	gpart commit "$diskdev" 2> /dev/null
133	case "$FSTYPE" in
134	ufs)
135		growfs -y /dev/"$rootdev"
136		;;
137	zfs)
138		zpool online -e $pool $rootdev
139		;;
140	esac
141}
142
143load_rc_config $name
144run_rc_command "$1"
145