1#!/bin/sh
2#
3# Copyright (c) 2006  The FreeBSD Project
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: mdconfig
31# REQUIRE: swap root
32
33. /etc/rc.subr
34
35name="mdconfig"
36stop_cmd="mdconfig_stop"
37start_cmd="mdconfig_start"
38start_precmd='[ -n "${_mdconfig_list}" ]'
39required_modules="geom_md:g_md"
40
41is_readonly()
42{
43	local _mp _ret
44
45	_mp=$1
46	_ret=`mount | while read _line; do
47		case ${_line} in
48		*" ${_mp} "*read-only*)
49			echo "yes"
50			;;
51
52		*)
53			;;
54		esac;
55	done`
56
57	if [ -n "${_ret}" ]; then
58		return 0
59	else
60		return 1
61	fi
62}
63
64init_variables()
65{
66	local _i
67
68	_fs=""
69	_mp=""
70	_dev="/dev/${_md}"
71	eval _config=\$mdconfig_${_md}
72	eval _newfs=\$mdconfig_${_md}_newfs
73
74	_type=${_config##*-t\ }
75	_type=${_type%%\ *}
76	if [ -z "${_type}" ]; then
77		err 1 "You need to specify \"-t <type>\" in mdconfig_${_md}"
78	fi
79
80	if [ "${_type}" = "vnode" ]; then
81		_file=${_config##*-f\ }
82		_file=${_file%%\ *}
83		if [ -z "${_file}" ]; then
84			err 2 "You need to specify \"-f <file>\" in mdconfig_${_md} for vnode devices"
85		fi
86		if [ "${_file}" != "${_file%.uzip}" ]; then
87			_dev="/dev/${_md}.uzip"
88		fi
89		for _i in `df ${_file} 2>/dev/null`; do _fs=${_i}; done
90	fi
91
92	# Debugging help.
93	debug "${_md} config: ${_config}"
94	debug "${_md} type: ${_type}"
95	debug "${_md} dev: ${_dev}"
96	debug "${_md} file: ${_file}"
97	debug "${_md} fs: ${_fs}"
98	debug "${_md} newfs flags: ${_newfs}"
99}
100
101mdconfig_start()
102{
103	local _md _mp _config _type _dev _file _fs _newfs _fsck_cmd
104
105	for _md in ${_mdconfig_list}; do
106		init_variables ${_md}
107		# Create md(4) devices of types swap, malloc and vnode if the
108		# file is on the root partition.
109		if [ "${_type}" != "vnode" -o "${_fs}" = "/" ]; then
110			if [ "${_type}" = "vnode" ]; then
111				if is_readonly ${_fs}; then
112					warn "${_fs} is mounted read-only, skipping ${_md}."
113					continue
114				fi
115				if [ "${_file}" != "${_file%.uzip}" ]; then
116					load_kld -m g_uzip geom_uzip || return 3
117					# sleep a bit to allow creation of /dev/mdX.uzip
118					sleep 2
119				fi
120			fi
121			if mdconfig -l -u ${_md} >/dev/null 2>&1; then
122				err 3 "${_md} already exists"
123			fi
124			echo "Creating ${_md} device (${_type})."
125			if ! mdconfig -a ${_config} -u ${_md}; then
126				echo "Creating ${_md} device failed, moving on."
127				continue
128			fi
129			# Skip fsck for uzip devices.
130			if [ "${_type}" = "vnode" ]; then
131				if [ "${_file}" != "${_file%.uzip}" ]; then
132					_fsck_cmd=":"
133				elif checkyesno background_fsck; then
134					_fsck_cmd="fsck -F"
135				else
136					_fsck_cmd="fsck"
137				fi
138				if ! eval ${_fsck_cmd} -p ${_dev} >/dev/null; then
139					echo "Fsck failed on ${_dev}, not mounting the filesystem."
140					continue
141
142				fi
143			else
144				newfs ${_newfs} ${_dev} >/dev/null
145			fi
146			if mount -d ${_dev} 2>&1 >/dev/null; then
147				echo "Mounting ${_dev}."
148				mount ${_dev}
149			fi
150		fi
151	done
152}
153
154mdconfig_stop()
155{
156	local _md _mp _config _type _dev _file _fs _newfs _i
157
158	for _md in ${_mdconfig_list}; do
159		init_variables ${_md}
160		if [ "${_type}" != "vnode" -o "${_fs}" = "/" ]; then
161			for _i in `df ${_dev} 2>/dev/null`; do _mp=${_i}; done
162			if [ -z "${_mp}" -o "${_mp}" != "${_mp%%%}" ]; then
163				echo "Device ${_dev} isn't mounted."
164			else
165				echo "Umounting ${_dev}."
166				umount ${_dev}
167			fi
168			if mdconfig -l -u ${_md} >/dev/null 2>&1; then
169				echo "Destroying ${_md}."
170				mdconfig -d -u ${_md}
171			fi
172		fi
173	done
174}
175
176_mdconfig_cmd="$1"
177if [ $# -gt 0 ]; then
178        shift
179fi
180[ -n "$*" ] && _mdconfig_list="$*"
181
182load_rc_config $name
183
184if [ -z "${_mdconfig_list}" ]; then
185	for _mdconfig_config in `list_vars mdconfig_md[0-9]\* |
186		sort_lite -nk1.12`
187	do
188		_mdconfig_unit=${_mdconfig_config#mdconfig_md}
189		_mdconfig_list="$_mdconfig_list md$_mdconfig_unit"
190	done
191	_mdconfig_list="${_mdconfig_list# }"
192fi
193
194run_rc_command "${_mdconfig_cmd}"
195