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