slicefix 5.59 KB
Newer Older
1
2
3
#!/bin/sh
#
# EMULAB-COPYRIGHT
4
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
5
6
7
# All rights reserved.
#

Mike Hibler's avatar
Mike Hibler committed
8
9
10
11
if [ -r /etc/emulab/paths.sh ]; then
	. /etc/emulab/paths.sh
else
	BINDIR=/etc/testbed
12
	BOOTDIR=/var/emulab/boot
Mike Hibler's avatar
Mike Hibler committed
13
14
fi

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
disk="ad0"

case $# in
1)
	part=$1
	;;
2)
	part=$1
	disk=$2
	;;
*)
	echo "Usage: $0 partition [disk]"
	exit 1
esac

dofreebsd() {
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
	#
	# ARGH!  FreeBSD 5, which primarily uses UFS2, internally converts
	# UFS1 filesystems to an updated, UFS2 compatible form.  However,
	# some of the converted fields leak back to disk when the filesystem
	# is unmounted, creating the potential for corruption in the following
	# scenerio:
	#
	# 1. mount, update, and unmount a UFS1 FS under FBSD5
	# 2. mount, update, and unmount the FS under FBSD4
	# 3. go back and access the FS under FBSD5
	#
	# #2 will update the old version of the csum structure.  At step
	# #3, the mount will see some of the leaked info from the unmount
	# in #1 and determine that it has already "upgraded" this FS and
	# thus doesn't need to copy the old csum into the new one.  The
	# result is that it will use stale csum info.
	#
	# In theory we could encounter this problem when we slicefix
	# a newly loaded FBSD image (#1), boot up and update stuff on
	# the image (#2), and then create a new image with imagezip
	# (#3, as imagezip uses the FBSD5 filesystem logic).
	#
	# How do we deal with this?  What we will have to do is either
	# fix the FBSD5 filesystem code or we will have to run a little
	# hack after the slicefix unmount to undo the damage that FBSD5
	# does.  Currently I have not done either.  Instead we avoid the
	# problem as follows.  Before making any change to the FS with
	# slicefix, we first RO-mount the FS to see if anything needs to
	# be done.  If not, we just leave it alone.  Since I currently
	# create all new images on machines with "ad" disks and that is
	# what the default fstab contains for its root device, we avoid
	# making any mods with slicefix and thus avoid #1 above.
	#
	# This is clearly not a solution.
	#
	version=`uname -v | sed -e 's/FreeBSD \([0-9]\).*/\1/'`

68
	# see if there is a root ('a') partition on this BSD slice
Mike Hibler's avatar
Mike Hibler committed
69
	`disklabel ${disk}s${part} 2>&1 | grep -s -E '^[ ]+a:' >/dev/null` || {
70
71
72
73
74
75
76
77
78
		return 1
	}

	rootdev=/dev/${disk}s${part}a
	echo "fixing FreeBSD root partition ${disk}s${part}a"
	fsck -p $rootdev || {
		echo "Fsck of $rootdev failed"
		return 1
	}
79
80
81
82
83
84
85
86
87
88
89
90
91
	mount -o ro $rootdev /mnt || {
		echo "RO-mount of $rootdev failed"
		return 1
	}

	# If our disk appears anywhere in fstab, assume we are good to go
	if `grep "^/dev/${disk}s" /mnt/etc/fstab >/dev/null 2>&1`; then
		umount $rootdev
		return 0
	fi

	# We need to change something, remount RW and change it
	umount $rootdev
92
93
94
95
	mount $rootdev /mnt || {
		echo "Mount of $rootdev failed"
		return 1
	}
Mike Hibler's avatar
Mike Hibler committed
96
	sed -E -i .orig -e "s;^/dev/[a-zA-Z]+[0-9]+s[0-9]+;/dev/${disk}s${part};" /mnt/etc/fstab || {
97
98
99
100
		echo "Failed to update /etc/fstab"
		umount $rootdev
		return 1
	}
Mike Hibler's avatar
Mike Hibler committed
101
	sed -E -i .orig -e "s;^/dev/[a-zA-Z]+[0-9]+s[0-9]+;/dev/${disk}s${part};" /mnt/etc/dumpdates || {
102
103
104
105
106
		echo "Failed to update /etc/dumpdates"
		umount $rootdev
		return 1
	}
	umount $rootdev
107
108
109
110
111
112

	# XXX need to fixup FS, see big comment above
	if [ "x$version" = "x5" ]; then
		echo "WARNING: FBSD5 may have modified the UFS1 root FS"
	fi

113
114
115
116
	return 0
}

dolinux() {
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
	# figure out the linux device name
	dunit=`echo $disk | sed -e 's/..\([0-7]\)/\1/'`
	case $disk in
	# IDE
	ad[0-3])
		dtype="hd"
		d=`echo $dunit | sed -e 'y/0123/048c/'`
		lrootdev="3${d}${part}"
		;;
	# SATA
	ad[4-7])
		dtype="sd"
		dunit=`expr $dunit - 4`
		lrootdev="8${dunit}${part}"
		;;
	# SCSI
	da[0-7])
		dtype="sd"
		lrootdev="8${dunit}${part}"
		;;
	*)
		echo "slicefix: linux: unknown disk $disk"
		return 1
		;;
	esac
	dunit=`echo $dunit | sed -e 'y/01234567/abcdefgh/'`;
	ldisk=$dtype$dunit

	# attempt to mount filesystem   
	rootdev=/dev/${disk}s${part}
	mount -t ext2fs $rootdev /mnt || {
		echo "EXT2FS mount of $rootdev failed"
		return 1
	}

	# change the swap devices in fstab
	sed -i .orig -e "s;^/dev/[hs]d.\([0-7]\);/dev/${ldisk}\1;" /mnt/etc/fstab || {
		echo "Failed to update /etc/fstab"
		umount $rootdev
		return 1
	}

	# update lilo.conf and set indicator to tell Emulab to rerun lilo
	sed -i .orig -e "s;\([br]oot=/dev\)/[hs]d.\([0-7]\);\1/${ldisk}\2;" /mnt/etc/lilo.conf || {
		echo "Failed to update /etc/lilo.conf"
		umount $rootdev
		return 1
	}
165
166
167
168
169

	# XXX note the hardwired path, cannot use BOOTDIR as it is different
        # in frisbee MFS.  This also assumes Linux partition is one big
	# filesystem.
	cp /dev/null /mnt/var/emulab/boot/runlilo
170
171
172
173
174
175
176
177
178

	umount $rootdev

	# setup one time lilo command line, must be done after unmount
	$BINDIR/groklilo -c "linux root=$lrootdev" $part /dev/$disk || {
		echo "Failed to set LILO command line"
		return 1
	}

Mike Hibler's avatar
Mike Hibler committed
179
	return 0
180
181
}

Mike Hibler's avatar
Mike Hibler committed
182
183
fixone() {
    echo "*** ${disk}s${part}:"
184
    ptype=`fdisk -${part} ${disk} | grep sysid | sed 's/^sysid \([0-9][0-9]*\).*/\1/'`
Mike Hibler's avatar
Mike Hibler committed
185
186
187
188
    ptype=${ptype:-0}

    case $ptype in
    165)
189
	dofreebsd
Mike Hibler's avatar
Mike Hibler committed
190
	return $?
191
	;;
Mike Hibler's avatar
Mike Hibler committed
192
193
194
    131)
	dolinux
	return $?
195
	;;
Mike Hibler's avatar
Mike Hibler committed
196
197
198
199
    0)
	echo "unused"
	;;
    *)
200
201
	echo "ignoring partition type $ptype"
	;;
Mike Hibler's avatar
Mike Hibler committed
202
203
204
205
206
207
208
209
210
211
212
    esac
    return 0
}

case $part in
0)
    part=1; fixone
    part=2; fixone
    part=3; fixone
    part=4; fixone

213
214
215
216
217
    # when fixing all partitions, do not fail on an error
    if [ $? -ne 0 ]; then
    	echo "WARNING: failed to fix one or more partitions, BEWARE!"
    fi

Mike Hibler's avatar
Mike Hibler committed
218
219
220
221
222
223
224
225
226
227
228
229
    # for the CD boot, we need to intialize the magic boot block
    if [ -e /cdrom.inf -a -x $BINDIR/tbbootconfig ]; then
	$BINDIR/tbbootconfig -f -c 1 -k 0 -m 1 /dev/${disk}
    fi
    ;;
1|2|3|4)
    fixone
    ;;
*)
    echo "bad partition: $part"
    false
    ;;
230
231
esac

Mike Hibler's avatar
Mike Hibler committed
232
exit $?