[EMAIL PROTECTED] (Joerg Wunsch) wrote:
> The biggest problem of all this is, of course, the bootstrapping
> step. The bootstrap still needs an `a' partition in order to read
> at least /boot/loader etc. from. The solution is to produce a faked
> overlay `a' partition that sits at exactly the point where the
> corresponding vinum subdisk of the root device is located.
Here's the first cut of a script that would set this up.
--
cheers, J"org .-.-. --... ...-- -.. . DL8DTL
http://www.sax.de/~joerg/ NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)
#!/usr/bin/perl -w
#
# Copyright (c) 2003 Joerg Wunsch
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD$
#
# Create overlay partition `a' for all devices that are part of the
# named vinum root volume.
$ENV{PATH} = "/sbin:/bin:/usr/sbin:/usr/bin";
if (defined($ENV{TMPDIR})) {
$tmpdir = $ENV{TMPDIR};
} else {
$tmpdir = "/tmp";
}
$tempname = "${tmpdir}/vinum-a-part.$$";
die "usage: $0 <rootvolname>\n" unless $#ARGV == 0;
$rootvol = $ARGV[0];
$nsds = $nlines = 0;
# First, find out the components of our ${rootvol}. Make sure all our
# plexes have only one subdisks, and are of type "concat". Remember
# the subdisks found for step #2.
open(V, "vinum l -r $rootvol|") || die "Cannot start vinum(8)\n";
while (<V>) {
chomp;
if (/^P/) {
/^P\s+(\S+)\s+([CSR5]+)\s+.*Subdisks:\s+(\d+)/;
$pname = $1;
$org = $2;
$nsd = $3;
$nsd > 1 && die "Plex $pname has more than one subdisk.\n";
$org ne "C" && die "Plex $pname is not a concat plex.\n";
} elsif (/^S/) {
/^S\s+(\S+)\s/;
$sdnames[$nsds++] = $1;
}
$nlines++;
}
close(V);
die "Volume $rootvol not found.\n" unless $nlines > 0;
die "Volume $rootvol has no subdisks.\n" unless $nsds > 0;
# Now, for each of the subdisks found, determine size and offset
# inside the vinum drive. Then figure out the disk device (and
# perhaps slice) it belongs to. Analyze the label of that device, to
# see whether the vinum partition is really there.
# If there is already an `a' partition, analyze it. If it already
# matches our expectations, just proceed. If it is inside the vinum
# partition but has wrong parameters, leave it to the operator for a
# manual fix, and proceed. If it is outside vinum, try moving it into
# one of the partition slots `d' through `h'. Failing this, proceed
# to the next subdisk.
# If successful, create a new label with our new `a' partition.
foreach $sd (@sdnames) {
open(V, "vinum l -v $sd 2>/dev/null |") || die "Cannot start vinum(8)\n";
$size = $offset = 0;
$devname = $dev = $part = "";
while (<V>) {
if (/Size:\s+(\d+)\s+bytes/) {
$size = $1;
} elsif (/Drive\s+\S+\s+[(](\S+)[)].*offset\s+(\d+)/) {
$devname = $1;
$offset = $2;
}
}
close(V);
die "Cannot find parameters for sd $sd.\n" unless
$size > 0 && $offset > 0 && $devname ne "";
$devname =~ s,^/dev/,,;
$devname =~ m|^([a-z]+\d+(s\d+)?)([a-h])$|;
$dev = $1;
$part = $3;
die "Cannot figure out device and partition from $devname.\n"
unless $dev ne "" && $part ne "";
$size /= 512;
$offset /= 512;
system("disklabel $dev > $tempname") &&
die "Cannot run disklabel(8)\n";
%parts = ();
$blurb = "";
open(L, $tempname) || die "Cannot read temp file $tempname\n";
while (<L>) {
if (/^\s+([a-h]):/) {
chomp;
$parts{$1} = $_;
} else {
$blurb .= $_;
}
}
close(L);
unlink $tempname;
die "Vinum partition ${part} not found on ${dev}\n"
unless defined($parts{$part});
$parts{$part} =~ /:\s+(\d+)\s+(\d+)\s+(\S+)/;
$vinsize = $1;
$vinoff = $2;
die "Vinum partition ${part} on ${dev} not type `vinum'\n"
unless $3 eq "vinum";
if (defined($parts{a})) {
print "${dev}: existing `a' partition found, ";
$parts{a} =~ /:\s+(\d+)\s+(\d+)/;
$psize = $1;
$poff = $2;
if ($poff >= $vinoff && $poff + $psize <= $vinoff + $vinsize) {
# `a' partition overlaps vinum partition
if ($poff == $vinoff + $offset &&
$psize == $size) {
print "already correctly set up.\n";
next;
}
print "is inside the vinum partition but wrong.\n";
printf "Size/offset %d/%d, should be %d/%d,manual fix required.\n",
$psize, $poff, $size, $vinoff + $offset;
next;
}
for ($c = 'd'; $c <= 'h'; $c++) {
if (!defined($parts{$c})) {
print "will be moved to partition `$c'\n";
$parts{a} =~ s/^\s+a:/ $c:/;
$parts{$c} = $parts{a};
$parts{a} = undef;
last;
}
}
if ($c > 'h') {
print "cannot be moved, no free slot.\n";
next;
}
}
$parts{a} = " a: ${size} " . ($vinoff + $offset) . " 4.2BSD 2048 16384 0";
open(L, ">${tempname}") || die "Cannot create ${tempname}.\n";
print L $blurb;
foreach $p (sort(keys(%parts))) {
print L $parts{$p} . "\n";
}
close(L);
system("disklabel -R $dev ${tempname}") &&
die "disklabel $dev failed ($?)\n";
unlink $tempname;
print "${dev}: partition `a' successfully created.\n";
}