[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";
}

Reply via email to