xref: /illumos-gate/usr/src/cmd/stmsboot/mpxio-upgrade (revision 613b28719c10e84c1202c1045df44d77767de21d)
1#!/sbin/sh
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22#
23# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26
27. /lib/svc/share/fs_include.sh
28. /lib/svc/share/net_include.sh
29
30# Make sure that the essential libraries can be found.
31LD_LIBRARY_PATH=/lib; export LD_LIBRARY_PATH
32STMSBOOTUTIL=/lib/mpxio/stmsboot_util
33SAVEDIR=/etc/mpxio
34RECOVERFILE=$SAVEDIR/recover_instructions
35DEVFSADM=/usr/sbin/devfsadm
36DUMPADM=/usr/sbin/dumpadm
37METADEVADM=/usr/sbin/metadevadm
38usrmounted=0
39MACH=`/usr/bin/uname -p`
40CP=/usr/bin/cp
41DF=/usr/bin/df
42LS=/usr/bin/ls
43RM=/usr/bin/rm
44EGREP=/usr/bin/egrep
45SED=/usr/bin/sed
46ZPOOL=/usr/sbin/zpool
47AWK=/usr/bin/awk
48MOUNT=/sbin/mount
49UMOUNT=/sbin/mount
50EEPROM=/usr/sbin/eeprom
51BOOTADM=/usr/sbin/bootadm
52SVCADM=/usr/sbin/svcadm
53
54mpxio_error()
55{
56	cecho "\nERROR: stmsboot: $1"
57	#
58	# display recovery instructions - the first call logs to the service
59	# log and the second call displays on the console.
60	#
61	shcat $RECOVERFILE
62	shcat $RECOVERFILE >/dev/msglog 2>&1
63	cecho "These instructions were also logged to the file $RECOVERFILE\n"
64}
65
66#
67# root ("/") is already mounted read only by the kernel.
68# Remount the root read-write.
69#
70mpxio_mount_root()
71{
72	HASZFSROOT=`$DF -g / |grep zfs`
73
74	# In single-user maintenance mode, we don't have a writable
75	# root partition, so we _cannot_ use devlinks. Therefore we
76	# have to do some dancing - first mount the physical path
77	# read-write, then re-run $STMSBOOTUTIL to get the real
78	# devlink mapping, and then re-mount the root slice. Of course,
79	# if we all used ZFS this wouldn't be such a pain!
80	exec < $vfstab; readvfstab /
81	# ZFS root environments should _not_ have an entry for /
82	# in their /etc/vfstab.
83	if [ "x$special" != "x" ]; then
84		# sanity check for ZFSRoot _and_ / in /etc/vfstab
85		if [ "x$HASZFSROOT" != "x" ]; then
86			# ERROR - this would cause a failure later
87			# so let root know about it now and provide
88			# a chance to handle it before filesystem/usr
89			cecho "stmsboot: System has ZFS Root *and* an entry for / in /etc/vfstab\nstmsboot: Please remove the / entry from /etc/vfstab and then run\n# svcadm clear mpxio-upgrade"
90			exit 1
91		fi
92		ISPHYS=`echo $special |$AWK '/^\/dev\/dsk/ {print}'`;
93		if [ "x$ISPHYS" != "x" ]; then
94			new_special=`$STMSBOOTUTIL -m $special`
95			if [ "x$new_special" = "xNOT_MAPPED" ]; then
96				# this is a bad state to be in, exit
97				cecho "Error: Your root device is not mapped."
98				exit 1
99			fi
100	       		checkopt "llock" $mntopts
101			mntopts='remount'
102			[ -n "$otherops" ] && mntopts="${mntopts},${otherops}"
103			$MOUNT -m -F $fstype -o $mntopts $new_special \
104				$mountp >/dev/msglog 2>&1
105
106			# now re-run $STMSBOOTUTIL to get the real mapping
107			new_special=`$STMSBOOTUTIL -m $special`
108		else
109			# a metadevice, either /dev/md or /dev/vx
110			new_special=$special
111		fi
112		# mount root for real
113		$MOUNT -o remount,rw $new_special / >/dev/msglog 2>&1
114	else
115		if [ "x$HASZFSROOT" = "x" ]; then
116			cecho "stmsboot: Error: your root slice is invalid"
117			exit 1
118		else
119			cecho "stmsboot: Root is on ZFS"
120		fi
121	fi
122}
123
124#
125# mount /usr read only
126#
127mpxio_mount_usr()
128{
129	exec < $vfstab; readvfstab "/usr"
130	ret_val=0
131	if [ -n "$mountp" ]; then
132		new_special=`$STMSBOOTUTIL -m $special`
133
134		if [ "$fstype" = cachefs ]; then
135			# Mount read-only without the cache.
136			case "$mntopts" in
137			*backfstype=nfs*)
138				cfsbacktype=nfs
139				;;
140			*backfstype=hsfs*)
141				cfsbacktype=hsfs
142				;;
143			*)
144				cecho 'stmsboot: invalid vfstab entry for /usr'
145				cfsbacktype=nfs
146				;;
147			esac
148			# see the comment below for /dev/null
149			$MOUNT -m -F $cfsbacktype -o ro $new_special $mountp \
150>/dev/null 2>&1
151			ret_val=$?
152		else
153			#
154			# Must use -o largefiles here to ensure the read-only
155			# mount does not fail as a result of having a large
156			# file present on /usr.
157			#
158			if [ "x$mntopts" = x- ]; then
159				mntopts='ro,largefiles'
160			else
161				checkopt largefiles $mntopts
162				if [ "x$option" != xlargefiles ]; then
163					mntopts="largefiles,$mntopts"
164				fi
165
166				checkopt ro $mntopts
167				if [ "x$option" != xro ]; then
168					mntopts="ro,$mntopts"
169				fi
170
171				# Requesting logging on a read-only mount
172				# causes errors to be displayed, so remove
173				# "logging" from the list of options.
174				checkopt logging $mntopts
175				if [ "x$option" = xlogging ]; then
176					mntopts="$otherops"
177				fi
178			fi
179
180			# In case of a manual restart of the service, mount
181			# will emit messages if /usr is already mounted.
182			# So redirect the output to /dev/null.
183			$MOUNT -m -F $fstype -o $mntopts $new_special /usr \
184>/dev/null 2>&1
185			ret_val=$?
186		fi
187		if [ $ret_val -eq 0 ]; then
188			usrmounted=1
189		fi
190	fi
191
192	return $ret_val
193}
194
195# update system dump configuration
196update_dumpconf()
197{
198	# Disable device-in-use checking (done in libdiskmgt).
199	# Without disabling this check, the configuration of dump device
200	# would fail as the device-in-use code incorrectly concludes that
201	# the device is in use and hence prevents configuration of the dump
202	# device.
203	NOINUSE_CHECK=1
204	export NOINUSE_CHECK
205
206	DUMPISZFS=`$AWK -F"=" '/DUMPADM_DEVICE/ {print $2}' /etc/dumpadm.conf|$EGREP zvol`
207	if [ "x$DUMPISZFS" = "x" ]; then
208		set -- `$DUMPADM -u 2>&1 | $EGREP 'cannot use /dev.* as dump device'`
209		if [ "x$4" != x ]; then
210			newname=`$STMSBOOTUTIL -m $4`
211			if [ $? -eq 0 ]; then
212				if $DUMPADM -d $newname > /dev/msglog 2> /dev/console; then
213					cecho "stmsboot: dump configuration \
214					has been updated."
215				else
216					mpxio_error "failed to configure \
217					the dump device.\nold \
218					dump device name: $4"
219					return 1
220				fi
221			fi
222		fi
223	else
224		# make sure we can get to it, force zfs to load fully
225		$LS $DUMPISZFS >>/dev/null 2>&1
226		cecho "stmsboot: dump on ZFS, no dumpadm update required"
227	fi
228	return 0
229}
230
231# Update bootpath for x86 here when we are enabling mpxio on root
232update_bootpath()
233{
234	cur_bootpath=`$STMSBOOTUTIL -b`
235	if [ $? != 0 ]; then
236		cecho "stmsboot: ERROR! Unable to retrieve bootpath property\n"
237		exit 1
238	fi
239
240	NEWBOOTPATH=""
241	for path in $cur_bootpath; do
242		mapped=`$STMSBOOTUTIL -p $path`
243		if [ "$mapped" != "NOT_MAPPED" ]; then
244			if [ "x$mapped" != "x$path" ]; then
245				NEWBOOTPATH=`echo "$path " | \
246				    $SED -e"s|$path|$mapped|"`" $NEWBOOTPATH"
247			else
248				NEWBOOTPATH="$NEWBOOTPATH $path"
249			fi
250		fi
251	done
252	# now strip off leading and trailing space chars
253	new_bootpath=`echo $NEWBOOTPATH`
254	$EEPROM bootpath="$new_bootpath"
255	cecho "stmsboot: bootpath has been updated, now regenerating boot archive"
256	$BOOTADM update-archive
257	cecho ""
258}
259
260# Now do the actual work
261mpxio_main()
262{
263	# NOTE: If the first attempt to run the service has failed due to an
264	# expected error, users should be able to manually rerun the service.
265	#
266	# First mount /usr read only. This must be done to run
267	# utilities such as fsck and devfsadm.
268	# In the case of a manual rerun of the service, mounting of /usr here
269	# fails if /usr already happens to be mounted. It is better that we
270	# do not mount /usr if already mounted, but there seems to be no
271	# apparent way to check whether /usr is mounted or not as we mount
272	# /usr without making an entry into /etc/mnttab. So instead of
273	# explicitly checking for mount failures, we just do a sanity check
274	# by looking for some file (in this case devfsadm) in /usr.
275	#
276	mpxio_mount_usr
277	if [ ! -s $DEVFSADM ]; then
278		mpxio_error "failed to mount the /usr filesystem."
279		return
280	fi
281
282	if mpxio_mount_root; then
283		# create /dev links
284		cecho "stmsboot: configuring devices"
285		$DEVFSADM
286
287		# update /etc/vfstab to reflect device name changes
288		$STMSBOOTUTIL -u >/dev/msglog 2>&1
289		if [ $? -eq 0 ]; then
290			$CP /etc/vfstab /etc/vfstab.old
291			$CP $SAVEDIR/vfstab.new /etc/vfstab
292			$RM $SAVEDIR/vfstab.new
293			cecho ""
294			cecho "stmsboot: vfstab has been updated"
295			if update_dumpconf; then
296				# update svm configuration to reflect new names
297				if [ -s /kernel/drv/md.conf ] && \
298				    [ -x $METADEVADM ]; then
299					$METADEVADM -r >/dev/msglog 2>&1
300				fi
301			fi
302			if [ "x$MACH" = "xi386" ]; then
303				# only update bootpath here for x86
304				update_bootpath
305			fi
306		else
307			mpxio_error "failed to update /etc/vfstab."
308		fi
309
310		$SVCADM disable system/device/mpxio-upgrade
311	else
312		mpxio_error "failed to mount the root filesystem."
313		if [ $usrmounted -eq 1 ]; then
314			$UMOUNT /usr
315		fi
316	fi
317}
318
319mpxio_main
320